| | <?php |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | if (!defined('ABSPATH')) { |
| | exit; |
| | } |
| |
|
| | |
| | define('PHI_SHAMPOO_VERSION', '1.0'); |
| | define('PHI_SHAMPOO_PLUGIN_DIR', plugin_dir_path(__FILE__)); |
| | define('PHI_SHAMPOO_PLUGIN_URL', plugin_dir_url(__FILE__)); |
| | define('PHI_SHAMPOO_PLUGIN_BASENAME', plugin_basename(__FILE__)); |
| |
|
| | |
| | define('PHI_SHAMPOO_TEXT_MODEL', 'microsoft/Phi-3.5-mini-instruct'); |
| | define('PHI_SHAMPOO_VISION_MODEL', 'microsoft/Phi-3.5-vision-instruct'); |
| | define('PHI_SHAMPOO_HF_TEXT_API_URL', 'https://api-inference.huggingface.co/models/' . PHI_SHAMPOO_TEXT_MODEL); |
| | define('PHI_SHAMPOO_HF_VISION_API_URL', 'https://api-inference.huggingface.co/models/' . PHI_SHAMPOO_VISION_MODEL); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_activate() { |
| | |
| | phi_shampoo_create_pages(); |
| | |
| | |
| | if (!get_option('phi_shampoo_test_mode')) { |
| | update_option('phi_shampoo_test_mode', true); |
| | } |
| | |
| | |
| | flush_rewrite_rules(); |
| | } |
| | register_activation_hook(__FILE__, 'phi_shampoo_activate'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_deactivate() { |
| | |
| | flush_rewrite_rules(); |
| | } |
| | register_deactivation_hook(__FILE__, 'phi_shampoo_deactivate'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_create_pages() { |
| | |
| | $analyzer_page_id = wp_insert_post(array( |
| | 'post_title' => 'Phi Shampoo Analyzer', |
| | 'post_content' => '[phi_shampoo_analyzer]', |
| | 'post_status' => 'publish', |
| | 'post_type' => 'page', |
| | 'comment_status' => 'closed' |
| | )); |
| | |
| | |
| | update_option('phi_shampoo_analyzer_page_id', $analyzer_page_id); |
| | } |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_enqueue_scripts() { |
| | |
| | wp_register_style('phi-shampoo-style', PHI_SHAMPOO_PLUGIN_URL . 'assets/css/style.css', array(), PHI_SHAMPOO_VERSION); |
| | wp_enqueue_style('phi-shampoo-style'); |
| | |
| | |
| | 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'); |
| | |
| | |
| | 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'); |
| |
|
| | |
| | |
| | |
| | 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); |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_add_settings_link($links) { |
| | $settings_link = '<a href="' . admin_url('admin.php?page=phi-shampoo-settings') . '">' . __('Settings', 'phi-shampoo-analyzer') . '</a>'; |
| | array_unshift($links, $settings_link); |
| | return $links; |
| | } |
| | add_filter('plugin_action_links_' . PHI_SHAMPOO_PLUGIN_BASENAME, 'phi_shampoo_add_settings_link'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_register_shortcodes() { |
| | add_shortcode('phi_shampoo_analyzer', 'phi_shampoo_analyzer_shortcode'); |
| | } |
| | add_action('init', 'phi_shampoo_register_shortcodes'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_analyzer_shortcode() { |
| | ob_start(); |
| | ?> |
| | <div class="phi-shampoo-analyzer"> |
| | <h2>Phi Shampoo Analyzer</h2> |
| | <p>Enter shampoo ingredients below or upload an image of the ingredient list.</p> |
| | |
| | <form id="phi-analyzer-form" method="post" enctype="multipart/form-data"> |
| | <?php wp_nonce_field('phi_shampoo_analyze', 'phi_shampoo_nonce'); ?> |
| | |
| | <div class="phi-form-group"> |
| | <label for="phi-ingredients">Ingredients:</label> |
| | <textarea id="phi-ingredients" name="ingredients" rows="5" placeholder="Enter ingredients separated by commas..."></textarea> |
| | </div> |
| | |
| | <div class="phi-form-group"> |
| | <label for="phi-image">Or upload image:</label> |
| | <input type="file" id="phi-image" name="ingredient_image" accept="image/*"> |
| | </div> |
| | |
| | <div class="phi-form-group"> |
| | <label for="phi-allergies">Known Allergies (optional):</label> |
| | <input type="text" id="phi-allergies" name="allergies" placeholder="e.g., Parabens, Sulfates, Fragrances"> |
| | </div> |
| | |
| | <div class="phi-form-group"> |
| | <label for="phi-skin-type">Skin Type (optional):</label> |
| | <select id="phi-skin-type" name="skin_type"> |
| | <option value="">Select Skin Type</option> |
| | <option value="Normal">Normal</option> |
| | <option value="Dry">Dry</option> |
| | <option value="Oily">Oily</option> |
| | <option value="Combination">Combination</option> |
| | <option value="Sensitive">Sensitive</option> |
| | </select> |
| | </div> |
| | |
| | <div class="phi-form-submit"> |
| | <button type="submit" class="phi-submit-button">Analyze</button> |
| | </div> |
| | </form> |
| | |
| | <div id="phi-result" class="phi-result" style="display: none;"> |
| | <h3>Analysis Result</h3> |
| | <div id="phi-result-content"></div> |
| | </div> |
| | |
| | <div id="phi-loading" class="phi-loading" style="display: none;"> |
| | <p>Analyzing ingredients... Please wait.</p> |
| | </div> |
| | </div> |
| | |
| | <script> |
| | jQuery(document).ready(function($) { |
| | $('#phi-analyzer-form').on('submit', function(e) { |
| | e.preventDefault(); |
| | |
| | $('#phi-loading').show(); |
| | $('#phi-result').hide(); |
| | |
| | var formData = new FormData(this); |
| | formData.append('action', 'phi_analyze_shampoo'); |
| | |
| | $.ajax({ |
| | url: phiShampoo.ajax_url, |
| | type: 'POST', |
| | data: formData, |
| | contentType: false, |
| | processData: false, |
| | success: function(response) { |
| | $('#phi-loading').hide(); |
| | |
| | if (response.success) { |
| | $('#phi-result-content').html(response.data.result); |
| | $('#phi-result').show(); |
| | } else { |
| | $('#phi-result-content').html('<p class="phi-error">Error: ' + response.data.message + '</p>'); |
| | $('#phi-result').show(); |
| | } |
| | }, |
| | error: function() { |
| | $('#phi-loading').hide(); |
| | $('#phi-result-content').html('<p class="phi-error">Error: Could not connect to the server.</p>'); |
| | $('#phi-result').show(); |
| | } |
| | }); |
| | }); |
| | }); |
| | </script> |
| | <?php |
| | return ob_get_clean(); |
| | } |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_ajax_analyze() { |
| | |
| | if (!isset($_POST['phi_shampoo_nonce']) || !wp_verify_nonce($_POST['phi_shampoo_nonce'], 'phi_shampoo_analyze')) { |
| | wp_send_json_error(array('message' => 'Security check failed.')); |
| | } |
| | |
| | $ingredients = ''; |
| | $image_uploaded = false; |
| | |
| | |
| | if (!empty($_FILES['ingredient_image']['tmp_name'])) { |
| | $image_uploaded = true; |
| | $tmp_name = $_FILES['ingredient_image']['tmp_name']; |
| | |
| | |
| | $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.')); |
| | } |
| | |
| | |
| | $allergies = isset($_POST['allergies']) ? sanitize_text_field($_POST['allergies']) : ''; |
| | $skin_type = isset($_POST['skin_type']) ? sanitize_text_field($_POST['skin_type']) : ''; |
| | |
| | |
| | $analysis_data = array( |
| | 'ingredients' => $ingredients, |
| | 'allergies' => $allergies, |
| | 'skin_type' => $skin_type |
| | ); |
| | |
| | $analysis = phi_shampoo_analyze_ingredients($analysis_data); |
| | |
| | if ($analysis['success']) { |
| | $html_result = '<div class="phi-analysis">'; |
| | |
| | if ($image_uploaded) { |
| | $html_result .= '<p><strong>Extracted Ingredients:</strong> ' . esc_html($ingredients) . '</p>'; |
| | } |
| | |
| | $html_result .= '<div class="phi-analysis-content">' . nl2br(esc_html($analysis['result'])) . '</div>'; |
| | $html_result .= '</div>'; |
| | |
| | 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'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_process_image($image_path) { |
| | |
| | $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" |
| | ); |
| | } |
| | |
| | |
| | $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' => '' |
| | ); |
| | } |
| | |
| | |
| | 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' => '' |
| | ); |
| | } |
| | |
| | |
| | $image_data = file_get_contents($image_path); |
| | $base64_image = base64_encode($image_data); |
| | |
| | |
| | $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 |
| | )); |
| | |
| | |
| | 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' => '' |
| | ); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_analyze_ingredients($data) { |
| | |
| | $test_mode = get_option('phi_shampoo_test_mode', false); |
| | if ($test_mode) { |
| | return phi_shampoo_generate_test_analysis($data); |
| | } |
| | |
| | |
| | $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.' |
| | ); |
| | } |
| | |
| | |
| | if (empty($data['ingredients'])) { |
| | return array( |
| | 'success' => false, |
| | 'error' => 'No ingredients provided for analysis.', |
| | 'result' => 'Error: No ingredients to analyze.' |
| | ); |
| | } |
| | |
| | |
| | $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"; |
| | |
| | |
| | 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"; |
| | } |
| | |
| | |
| | $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"; |
| | |
| | |
| | phi_shampoo_log("Analysis prompt: " . $prompt); |
| | |
| | |
| | $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 |
| | )); |
| | |
| | |
| | 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.' |
| | ); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | 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 |
| | ); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | function phi_shampoo_get_api_token() { |
| | $token = get_option('phi_shampoo_hf_api_token', ''); |
| | |
| | |
| | return $token; |
| | } |
| |
|
| | |
| | |
| | |
| | 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'); |
| |
|
| | |
| | |
| | |
| | function phi_shampoo_settings_page() { |
| | |
| | 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')) { |
| | |
| | |
| | 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); |
| | } |
| | |
| | |
| | $test_mode = isset($_POST['phi_shampoo_test_mode']) ? true : false; |
| | update_option('phi_shampoo_test_mode', $test_mode); |
| | |
| | echo '<div class="notice notice-success is-dismissible"><p>Settings saved successfully!</p></div>'; |
| | } else { |
| | echo '<div class="notice notice-error is-dismissible"><p>Security check failed. Settings not saved.</p></div>'; |
| | } |
| | } |
| | |
| | |
| | $api_token = get_option('phi_shampoo_hf_api_token', ''); |
| | $test_mode = get_option('phi_shampoo_test_mode', true); |
| | |
| | ?> |
| | <div class="wrap"> |
| | <h1>Phi Shampoo Analyzer Settings</h1> |
| | |
| | <form method="post" action=""> |
| | <?php wp_nonce_field('phi_shampoo_settings', 'phi_shampoo_settings_nonce'); ?> |
| | |
| | <table class="form-table"> |
| | <tr> |
| | <th scope="row">Hugging Face API Token</th> |
| | <td> |
| | <input type="password" name="phi_shampoo_hf_api_token" value="<?php echo esc_attr($api_token); ?>" class="regular-text" /> |
| | <p class="description"> |
| | Enter your Hugging Face API token. |
| | <a href="https://huggingface.co/settings/tokens" target="_blank">Get a token here</a>. |
| | </p> |
| | </td> |
| | </tr> |
| | <tr> |
| | <th scope="row">Test Mode</th> |
| | <td> |
| | <label> |
| | <input type="checkbox" name="phi_shampoo_test_mode" <?php checked($test_mode, true); ?> /> |
| | Enable test mode (uses pre-defined responses instead of API calls) |
| | </label> |
| | </td> |
| | </tr> |
| | </table> |
| | |
| | <div class="phi-shampoo-settings-info"> |
| | <h2>Important Information</h2> |
| | <p>To use this plugin, make sure:</p> |
| | <ul> |
| | <li>You have a valid Hugging Face account</li> |
| | <li>You have <a href="https://huggingface.co/settings/inference-providers" target="_blank">enabled the HF Inference API</a> in your Hugging Face account</li> |
| | <li>Your API token has the necessary permissions (at least "Read" access)</li> |
| | </ul> |
| | </div> |
| | |
| | <p class="submit"> |
| | <input type="submit" name="phi_shampoo_save_settings" class="button-primary" value="Save Settings" /> |
| | </p> |
| | </form> |
| | </div> |
| | <?php |
| | } |