'Phi Shampoo Analyzer', 'post_content' => '[phi_shampoo_analyzer]', 'post_status' => 'publish', 'post_type' => 'page', 'comment_status' => 'closed' )); // Save page ID to settings update_option('phi_shampoo_analyzer_page_id', $analyzer_page_id); } /** * Enqueue scripts and styles */ function phi_shampoo_enqueue_scripts() { // Register and enqueue CSS wp_register_style('phi-shampoo-style', PHI_SHAMPOO_PLUGIN_URL . 'assets/css/style.css', array(), PHI_SHAMPOO_VERSION); wp_enqueue_style('phi-shampoo-style'); // Register and enqueue JavaScript wp_register_script('phi-shampoo-script', PHI_SHAMPOO_PLUGIN_URL . 'assets/js/phi-shampoo.js', array('jquery'), PHI_SHAMPOO_VERSION, true); wp_enqueue_script('phi-shampoo-script'); // Localize the script with the ajax URL wp_localize_script('phi-shampoo-script', 'phiShampoo', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('phi_shampoo_nonce'), 'analyzePage' => get_permalink(get_option('phi_shampoo_analyzer_page_id')) )); } add_action('wp_enqueue_scripts', 'phi_shampoo_enqueue_scripts'); /** * Write to debug log */ function phi_shampoo_log($message) { if (defined('WP_DEBUG') && WP_DEBUG) { $log_file = WP_CONTENT_DIR . '/debug.log'; $timestamp = current_time('mysql'); if (is_array($message) || is_object($message)) { error_log('[' . $timestamp . '] Phi Shampoo: ' . print_r($message, true) . "\n", 3, $log_file); } else { error_log('[' . $timestamp . '] Phi Shampoo: ' . $message . "\n", 3, $log_file); } } } /** * Add settings link to plugins page */ function phi_shampoo_add_settings_link($links) { $settings_link = '' . __('Settings', 'phi-shampoo-analyzer') . ''; array_unshift($links, $settings_link); return $links; } add_filter('plugin_action_links_' . PHI_SHAMPOO_PLUGIN_BASENAME, 'phi_shampoo_add_settings_link'); /** * Register shortcodes */ function phi_shampoo_register_shortcodes() { add_shortcode('phi_shampoo_analyzer', 'phi_shampoo_analyzer_shortcode'); } add_action('init', 'phi_shampoo_register_shortcodes'); /** * Shampoo analyzer shortcode */ function phi_shampoo_analyzer_shortcode() { ob_start(); ?>

Phi Shampoo Analyzer

Enter shampoo ingredients below or upload an image of the ingredient list.

'Security check failed.')); } $ingredients = ''; $image_uploaded = false; // Handle image upload if (!empty($_FILES['ingredient_image']['tmp_name'])) { $image_uploaded = true; $tmp_name = $_FILES['ingredient_image']['tmp_name']; // Process image to extract ingredients $result = phi_shampoo_process_image($tmp_name); if ($result['success']) { $ingredients = $result['ingredients']; } else { wp_send_json_error(array('message' => 'Could not extract ingredients from image: ' . $result['error'])); } } else if (!empty($_POST['ingredients'])) { $ingredients = sanitize_textarea_field($_POST['ingredients']); } else { wp_send_json_error(array('message' => 'Please provide ingredients or upload an image.')); } // Gather additional data $allergies = isset($_POST['allergies']) ? sanitize_text_field($_POST['allergies']) : ''; $skin_type = isset($_POST['skin_type']) ? sanitize_text_field($_POST['skin_type']) : ''; // Analyze ingredients $analysis_data = array( 'ingredients' => $ingredients, 'allergies' => $allergies, 'skin_type' => $skin_type ); $analysis = phi_shampoo_analyze_ingredients($analysis_data); if ($analysis['success']) { $html_result = '
'; if ($image_uploaded) { $html_result .= '

Extracted Ingredients: ' . esc_html($ingredients) . '

'; } $html_result .= '
' . nl2br(esc_html($analysis['result'])) . '
'; $html_result .= '
'; wp_send_json_success(array('result' => $html_result)); } else { wp_send_json_error(array('message' => 'Analysis failed: ' . $analysis['error'])); } } add_action('wp_ajax_phi_analyze_shampoo', 'phi_shampoo_ajax_analyze'); add_action('wp_ajax_nopriv_phi_analyze_shampoo', 'phi_shampoo_ajax_analyze'); /** * Process image to extract ingredients using Phi-3.5 Vision */ function phi_shampoo_process_image($image_path) { // Check if in test mode $test_mode = get_option('phi_shampoo_test_mode', false); if ($test_mode) { phi_shampoo_log("Test mode active - returning test ingredients from image"); return array( 'success' => true, 'ingredients' => "Water, Sodium Laureth Sulfate, Cocamidopropyl Betaine, Sodium Chloride, Glycol Distearate, Dimethiconol, Fragrance, Carbomer, Guar Hydroxypropyltrimonium Chloride, Tetrasodium EDTA, Citric Acid, Sodium Benzoate, Methylchloroisothiazolinone, Methylisothiazolinone" ); } // Get API token $api_token = phi_shampoo_get_api_token(); if (empty($api_token)) { phi_shampoo_log("Error: Missing API token for Hugging Face"); return array( 'success' => false, 'error' => 'Missing API token. Please configure it in plugin settings.', 'ingredients' => '' ); } // Check if file exists if (!file_exists($image_path)) { phi_shampoo_log("Error: Image file not found at path: " . $image_path); return array( 'success' => false, 'error' => 'Image file not found.', 'ingredients' => '' ); } // Read and encode image $image_data = file_get_contents($image_path); $base64_image = base64_encode($image_data); // Make API request $api_url = defined('PHI_SHAMPOO_HF_VISION_API_URL') ? PHI_SHAMPOO_HF_VISION_API_URL : ''; $response = wp_remote_post($api_url, array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_token, 'Content-Type' => 'application/json' ), 'body' => json_encode(array( 'inputs' => array( 'image' => $base64_image, 'text' => "Extract all the ingredients from this shampoo product label. Format them as a comma-separated list." ) )), 'timeout' => 60 )); // Handle response if (is_wp_error($response)) { phi_shampoo_log("API Error: " . $response->get_error_message()); return array( 'success' => false, 'error' => $response->get_error_message(), 'ingredients' => '' ); } $body = wp_remote_retrieve_body($response); $status_code = wp_remote_retrieve_response_code($response); phi_shampoo_log("API Status: " . $status_code . ", Response: " . substr($body, 0, 200) . "..."); if ($status_code !== 200) { $error_message = "API Error: Received status code " . $status_code; $decoded = json_decode($body, true); if ($decoded && isset($decoded['error'])) { $error_message .= " - " . $decoded['error']; } return array( 'success' => false, 'error' => $error_message, 'ingredients' => '' ); } $decoded = json_decode($body, true); if (isset($decoded['generated_text'])) { return array( 'success' => true, 'ingredients' => $decoded['generated_text'] ); } else { return array( 'success' => false, 'error' => 'Unexpected response format', 'ingredients' => '' ); } } /** * Analyze ingredients using Phi-3.5 Text model */ function phi_shampoo_analyze_ingredients($data) { // Check if in test mode $test_mode = get_option('phi_shampoo_test_mode', false); if ($test_mode) { return phi_shampoo_generate_test_analysis($data); } // Get API token $api_token = phi_shampoo_get_api_token(); if (empty($api_token)) { return array( 'success' => false, 'error' => 'Missing API token. Please configure it in plugin settings.', 'result' => 'Error: API token not configured.' ); } // Check if ingredients are provided if (empty($data['ingredients'])) { return array( 'success' => false, 'error' => 'No ingredients provided for analysis.', 'result' => 'Error: No ingredients to analyze.' ); } // Build prompt for the model $prompt = "You are a shampoo ingredient analyzer. Please analyze the following shampoo ingredients for safety and potential allergic reactions:\n\n"; $prompt .= "Ingredients:\n" . $data['ingredients'] . "\n\n"; // Add user information if available if (!empty($data['allergies'])) { $prompt .= "User has allergies to: " . $data['allergies'] . "\n\n"; } if (!empty($data['skin_type'])) { $prompt .= "User has " . $data['skin_type'] . " skin type.\n\n"; } // Add analysis instructions $prompt .= "Please provide a detailed analysis including:\n"; $prompt .= "1. Overall safety assessment (safe or not safe for this user)\n"; $prompt .= "2. Potentially harmful ingredients with explanations\n"; $prompt .= "3. Specific concerns based on the user's health profile\n"; $prompt .= "4. Alternative recommendations if needed\n"; $prompt .= "\nBegin your response with a clear 'SAFE TO USE' or 'NOT RECOMMENDED' statement.\n"; // Log the prompt phi_shampoo_log("Analysis prompt: " . $prompt); // Make API request $api_url = defined('PHI_SHAMPOO_HF_TEXT_API_URL') ? PHI_SHAMPOO_HF_TEXT_API_URL : ''; $response = wp_remote_post($api_url, array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_token, 'Content-Type' => 'application/json' ), 'body' => json_encode(array( 'inputs' => $prompt, 'parameters' => array( 'max_new_tokens' => 512, 'temperature' => 0.7, 'do_sample' => true ) )), 'timeout' => 60 )); // Handle response if (is_wp_error($response)) { phi_shampoo_log("API Error: " . $response->get_error_message()); return array( 'success' => false, 'error' => $response->get_error_message(), 'result' => 'Error: API request failed. ' . $response->get_error_message() ); } $body = wp_remote_retrieve_body($response); $status_code = wp_remote_retrieve_response_code($response); phi_shampoo_log("API Status: " . $status_code . ", Response: " . substr($body, 0, 200) . "..."); if ($status_code !== 200) { $error_message = "API Error: Received status code " . $status_code; $decoded = json_decode($body, true); if ($decoded && isset($decoded['error'])) { $error_message .= " - " . $decoded['error']; } return array( 'success' => false, 'error' => $error_message, 'result' => 'Error: ' . $error_message ); } $decoded = json_decode($body, true); if (isset($decoded['generated_text'])) { return array( 'success' => true, 'result' => $decoded['generated_text'] ); } else { return array( 'success' => false, 'error' => 'Unexpected response format', 'result' => 'Error: Could not parse the AI response.' ); } } /** * Generate test analysis results (used when test mode is enabled) */ function phi_shampoo_generate_test_analysis($data) { $ingredients = $data['ingredients']; $has_allergies = !empty($data['allergies']); if (strpos(strtolower($ingredients), 'sulfate') !== false || strpos(strtolower($ingredients), 'methylisothiazolinone') !== false) { $result = "NOT RECOMMENDED\n\n"; $result .= "Based on the ingredients analysis, this shampoo contains some potentially problematic ingredients for your specific health profile.\n\n"; if (strpos(strtolower($ingredients), 'sodium laureth sulfate') !== false || strpos(strtolower($ingredients), 'sodium lauryl sulfate') !== false) { $result .= "• Sodium Laureth/Lauryl Sulfate: A strong detergent that can be irritating, especially for sensitive skin or those with certain allergies.\n"; } if (strpos(strtolower($ingredients), 'methylisothiazolinone') !== false) { $result .= "• Methylisothiazolinone: A preservative that is a known allergen and has been associated with skin sensitization.\n"; } if ($has_allergies) { $result .= "\nBased on your reported allergies, this product contains ingredients that may trigger a reaction. Consider alternative formulations labeled 'sulfate-free' and 'preservative-free'.\n"; } $result .= "\nRecommendation: Look for shampoos with gentler cleansing agents like Cocamidopropyl Hydroxysultaine, Sodium Cocoyl Isethionate or Coco Glucoside."; } else { $result = "SAFE TO USE\n\n"; $result .= "Based on the ingredients analysis, this shampoo appears to be safe for general use. The formula contains:\n\n"; $result .= "• Mild cleansing agents that effectively clean without excessive drying\n"; $result .= "• Conditioning agents to help maintain hair moisture\n"; if (strpos(strtolower($ingredients), 'fragrance') !== false || strpos(strtolower($ingredients), 'parfum') !== false) { $result .= "• Fragrances are present, which could potentially cause sensitivity in some individuals\n"; } $result .= "\nNo major red flags were identified in this formulation that would likely trigger adverse reactions."; } return array( 'success' => true, 'result' => $result ); } /** * Get the Hugging Face API token * Returns the API token from WordPress options or an empty string if not set */ function phi_shampoo_get_api_token() { $token = get_option('phi_shampoo_hf_api_token', ''); // For extra security, you can decrypt the token here if you stored it encrypted return $token; } /** * Admin menu */ function phi_shampoo_admin_menu() { add_menu_page( 'Phi Shampoo Analyzer', 'Phi Shampoo', 'manage_options', 'phi-shampoo-settings', 'phi_shampoo_settings_page', 'dashicons-admin-generic' ); } add_action('admin_menu', 'phi_shampoo_admin_menu'); /** * Admin settings page */ function phi_shampoo_settings_page() { // Save settings if submitted if (isset($_POST['phi_shampoo_save_settings']) && isset($_POST['phi_shampoo_settings_nonce'])) { if (wp_verify_nonce($_POST['phi_shampoo_settings_nonce'], 'phi_shampoo_settings')) { // Sanitize and save the API token if (isset($_POST['phi_shampoo_hf_api_token'])) { $api_token = sanitize_text_field($_POST['phi_shampoo_hf_api_token']); update_option('phi_shampoo_hf_api_token', $api_token); } // Save test mode setting $test_mode = isset($_POST['phi_shampoo_test_mode']) ? true : false; update_option('phi_shampoo_test_mode', $test_mode); echo '

Settings saved successfully!

'; } else { echo '

Security check failed. Settings not saved.

'; } } // Get current settings $api_token = get_option('phi_shampoo_hf_api_token', ''); $test_mode = get_option('phi_shampoo_test_mode', true); ?>

Phi Shampoo Analyzer Settings

Hugging Face API Token

Enter your Hugging Face API token. Get a token here.

Test Mode

Important Information

To use this plugin, make sure:

  • You have a valid Hugging Face account
  • You have enabled the HF Inference API in your Hugging Face account
  • Your API token has the necessary permissions (at least "Read" access)