'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.
Analyzing ingredients... Please wait.
'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);
?>