File: /mnt/data/dev/dev-wedolaundry/wp-content/functions.php.txt
<?php
// Sets up theme defaults and registers support for various WordPress features.
function qondri_theme_setup() {
// Make theme available for translation.
load_theme_textdomain( 'qondri', get_template_directory() . '/languages' );
// Add default posts and comments RSS feed links to head.
add_theme_support( 'automatic-feed-links' );
// Let WordPress manage the document title.
add_theme_support( 'title-tag' );
// Make Embed Responsive
add_theme_support( 'responsive-embeds' );
// Custom background color.
add_theme_support( 'custom-background' );
// Custom Header
add_theme_support( 'custom-header' );
// Enable woocommerce support
add_theme_support( 'woocommerce' );
// Enable support for Post Thumbnails on posts and pages.
add_theme_support( 'post-thumbnails' );
add_image_size( 'qondri-post-standard', 1170, 705, true );
add_image_size( 'qondri-post-widget', 69, 69, true );
add_image_size( 'qondri-project-standard', 1170, 533, true );
// Register menus
register_nav_menu( 'primary', esc_html__( 'Primary Menu', 'qondri' ) );
// Switch default core markup for search form, comment form, and comments to output valid HTML5.
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
) );
// Enable support for Post Formats.
add_theme_support( 'post-formats', array(
'image',
'gallery',
'video'
) );
/*
* This theme styles the visual editor to resemble the theme style,
* specifically font, colors, and column width.
*/
add_editor_style( array( 'assets/css/editor-style.css' ) );
}
add_action( 'after_setup_theme', 'qondri_theme_setup' );
// Enqueues scripts and styles.
function qondri_theme_scripts() {
// Core style & script for theme
wp_enqueue_style( 'animsition', get_template_directory_uri() . '/assets/css/animsition.css', array(), '4.0.1' );
wp_enqueue_style( 'elementor-icons-core', get_template_directory_uri() . '/assets/css/core-icons.css', array(), '1.0.0' );
wp_enqueue_script( 'animsition', get_template_directory_uri() . '/assets/js/animsition.js', array('jquery'), '4.0.1', true );
wp_enqueue_script( 'html5shiv', get_template_directory_uri() . '/assets/js/html5shiv.js', array('jquery'), '3.7.3', true );
wp_enqueue_script( 'respond', get_template_directory_uri() . '/assets/js/respond.js', array('jquery'), '1.3.0', true );
wp_enqueue_script( 'matchmedia', get_template_directory_uri() . '/assets/js/matchmedia.js', array('jquery'), '1.0.0', true );
wp_enqueue_script( 'easing', get_template_directory_uri() . '/assets/js/easing.js', array('jquery'), '1.3.0', true );
wp_enqueue_script( 'fitvids', get_template_directory_uri() . '/assets/js/fitvids.js', array('jquery'), '1.1.0', true );
// Theme Style
wp_enqueue_style( 'qondri-theme-style', get_stylesheet_uri(), array(), '1.0' );
wp_add_inline_style( 'qondri-theme-style', apply_filters( 'qondri_custom_colors_css', null ) );
// Theme Script
wp_enqueue_script( 'qondri-theme-script', get_template_directory_uri() . '/assets/js/main.js', array( 'jquery' ), '1.0', true );
// Carousel
$post_format = get_post_format();
if ( (is_single() && ( 'post-gallery' == $post_format )) ||
(is_singular('project') && qondri_get_mod( 'project_related', false )) ) {
wp_enqueue_style( 'slick', get_template_directory_uri() . '/assets/css/slick.css', array(), '1.0.0' );
wp_enqueue_script( 'slick', get_template_directory_uri() . '/assets/js/slick.js', array('jquery'), '1.0.0', true );
wp_enqueue_script( 'qondri-slide', get_template_directory_uri() . '/assets/js/slide.js', array('jquery'), '1.0.0', true );
}
// Woocommerce
if ( class_exists( 'woocommerce' ) ) {
if ( qondri_is_woocommerce_page() ||
qondri_is_woocommerce_shop() ||
qondri_is_woocommerce_archive_product() ||
is_woocommerce() || is_cart() || is_checkout() || is_account_page() ) {
wp_enqueue_style( 'woocommerce', get_template_directory_uri() . '/assets/css/woocommerce.css', array(), '1.0' );
}
}
// Comment JS
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) )
wp_enqueue_script( 'comment-reply' );
}
add_action( 'wp_enqueue_scripts', 'qondri_theme_scripts' );
// Registers a widget areas.
function qondri_sidebars_init() {
// Sidebar for Blog
register_sidebar( array(
'name' => esc_html__( 'Sidebar Blog', 'qondri' ),
'id' => 'sidebar-blog',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Blog.', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
// Sidebar for Pages
register_sidebar( array(
'name' => esc_html__( 'Sidebar Page', 'qondri' ),
'id' => 'sidebar-page',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Page', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
// Sidebar for Portfolio
register_sidebar( array(
'name' => esc_html__( 'Sidebar Portfolio', 'qondri' ),
'id' => 'sidebar-portfolio',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Portfolio', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
// Sidebar for Services
register_sidebar( array(
'name' => esc_html__( 'Sidebar Service', 'qondri' ),
'id' => 'sidebar-service',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Service', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
// Sidebar for Shop
register_sidebar( array(
'name' => esc_html__( 'Sidebar Shop', 'qondri' ),
'id' => 'sidebar-shop',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Shop', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
// 4 Sidebars for Footer
register_sidebar( array(
'name' => esc_html__( 'Sidebar Footer 1', 'qondri' ),
'id' => 'sidebar-footer-1',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Footer 1', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
register_sidebar( array(
'name' => esc_html__( 'Sidebar Footer 2', 'qondri' ),
'id' => 'sidebar-footer-2',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Footer 2', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
register_sidebar( array(
'name' => esc_html__( 'Sidebar Footer 3', 'qondri' ),
'id' => 'sidebar-footer-3',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Footer 3', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
register_sidebar( array(
'name' => esc_html__( 'Sidebar Footer 4', 'qondri' ),
'id' => 'sidebar-footer-4',
'description' => esc_html__( 'Add widgets here to appear in Sidebar Footer 4', 'qondri' ),
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h2 class="widget-title"><span>',
'after_title' => '</span></h2>'
) );
}
add_action( 'widgets_init', 'qondri_sidebars_init' );
// Include required files.
require( get_template_directory() . '/framework/get-mods.php' );
require( get_template_directory() . '/framework/theme-hooks.php' );
require( get_template_directory() . '/framework/theme-functions.php' );
require( get_template_directory() . '/framework/theme-admin.php' );
require( get_template_directory() . '/framework/fonts.php' );
require( get_template_directory() . '/framework/typography.php' );
require( get_template_directory() . '/framework/accent-color.php' );
require( get_template_directory() . '/framework/customizer/customizer.php' );
require( get_template_directory() . '/framework/elementor-options.php' );
require( get_template_directory() . '/framework/widget-areas.php' );
require( get_template_directory() . '/framework/breadcrumbs.php' );
require( get_template_directory() . '/framework/plugins.php' );
require( get_template_directory() . '/framework/theme-woocommerce.php' );
require( get_template_directory() . '/framework/demo-install.php' );
// Update checker
require( get_template_directory() . '/framework/update-checker/plugin-update-checker.php');
use YahnisElsts\PluginUpdateChecker\v5\PucFactory;
$settings = get_option('qondri_activate_settings');
$code = isset($settings['qondri_code_purchase']) ? $settings['qondri_code_purchase'] : '';
$site_url = parse_url(get_home_url());
$web = $site_url['host'];
$url = 'https://tplabs.co/api/checkUpdate?theme=qondri&code=' . $code . '&web=' . $web;
$MAEUpdateChecker = PucFactory::buildUpdateChecker(
$url,
get_template_directory() . '/functions.php',
'qondri'
);
add_filter('gform_pre_render_1', 'populate_date_fields');
add_filter('gform_pre_validation_1', 'populate_date_fields');
add_filter('gform_pre_submission_filter_1', 'populate_date_fields');
add_filter('gform_admin_pre_render_1', 'populate_date_fields');
function populate_date_fields($form) {
$collection_date_field_id = 53;
$delivery_date_field_id = 52;
// Set initial options for Collection Date
$collection_dates = [
['text' => 'Today', 'value' => date('d-m-Y')],
['text' => 'Tomorrow', 'value' => date('d-m-Y', strtotime('+1 day'))],
];
for ($i = 2; $i <= 7; $i++) {
$date = date('d-m-Y', strtotime("+$i days"));
$collection_dates[] = ['text' => $date, 'value' => $date];
}
foreach ($form['fields'] as &$field) {
if ($field->id == $collection_date_field_id) {
$field->choices = $collection_dates;
}
if ($field->id == $delivery_date_field_id) {
// Set placeholder for Delivery Date (to be replaced dynamically)
$field->choices = [['text' => 'Please select a collection date first', 'value' => '']];
}
}
return $form;
}
add_filter('gform_field_validation_1_52', 'disable_delivery_date_validation', 10, 4);
function disable_delivery_date_validation($result, $value, $form, $field) {
// Bypass validation by setting the result to true
$result['is_valid'] = true;
$result['message'] = ''; // Clear any existing validation message
return $result;
}
// // Populate fields for logged-in users
// add_filter( 'gform_field_value_user_name', function( $value ) {
// return is_user_logged_in() ? wp_get_current_user()->display_name : '';
// });
// add_filter( 'gform_field_value_user_email', function( $value ) {
// return is_user_logged_in() ? wp_get_current_user()->user_email : '';
// });
// add_filter( 'gform_field_value_user_phone', function( $value ) {
// return is_user_logged_in() ? get_user_meta( get_current_user_id(), 'phone', true ) : '';
// });
// Add Phone field to user profile
function add_phone_field_to_user_profile( $user ) {
?>
<h3>Extra Profile Information</h3>
<table class="form-table">
<tr>
<th><label for="phone">Phone</label></th>
<td>
<input type="text" name="phone" id="phone" value="<?php echo esc_attr( get_user_meta( $user->ID, 'phone', true ) ); ?>" class="regular-text" /><br />
<span class="description">Please enter your phone number.</span>
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'add_phone_field_to_user_profile' );
add_action( 'edit_user_profile', 'add_phone_field_to_user_profile' );
// Save Phone field for existing users
function save_phone_field( $user_id ) {
if ( !current_user_can( 'edit_user', $user_id ) ) {
return false;
}
update_user_meta( $user_id, 'phone', sanitize_text_field( $_POST['phone'] ) );
}
add_action( 'personal_options_update', 'save_phone_field' );
add_action( 'edit_user_profile_update', 'save_phone_field' );
// Save Phone field when a new user is created
function save_phone_field_on_new_user( $user_id ) {
if ( isset( $_POST['phone'] ) ) {
update_user_meta( $user_id, 'phone', sanitize_text_field( $_POST['phone'] ) );
}
}
add_action( 'user_register', 'save_phone_field_on_new_user' );
// Add Phone field to the Add New User form
function add_phone_field_to_new_user_form() {
?>
<h3>Extra Profile Information</h3>
<table class="form-table">
<tr>
<th><label for="phone">Phone</label></th>
<td>
<input type="text" name="phone" id="phone" value="" class="regular-text" /><br />
<span class="description">Please enter your phone number.</span>
</td>
</tr>
</table>
<?php
}
add_action( 'user_new_form', 'add_phone_field_to_new_user_form' );
// define('WP_DEBUG', true);
// define('WP_DEBUG_LOG', true);
//verfication code
// add_action('gform_pre_submission_1', 'send_verification_code');
// function send_verification_code($form) {
// // Log to confirm the function is triggered
// error_log('send_verification_code function triggered.');
// // Check if moving from page 4 to page 5
// $current_page = rgpost('gform_target_page_number_1');
// if ($current_page == 5) { // Page transition from 4 to 5
// error_log('Transitioning from page 4 to page 5.');
// // Check if the Checkout Method is "Register"
// $checkout_method_field_id = 82; // Checkout Method field ID
// $checkout_method = rgpost('input_' . $checkout_method_field_id);
// error_log('Checkout method selected: ' . $checkout_method); // Log selected checkout method
// if ($checkout_method === "No Account/ Register Now") { // Ensure exact match
// error_log('Checkout method is "Register". Sending verification code.');
// // Retrieve the email address entered on page 4
// $email_field_id = 78; // Email field ID on page 4
// $email = rgpost('input_' . $email_field_id);
// error_log('Email to send code to: ' . $email); // Log the email address
// // Generate a 6-digit verification code
// $verification_code = rand(100000, 999999);
// // Save the code to the session
// if (!session_id()) {
// session_start();
// }
// $_SESSION['verification_code'] = $verification_code;
// // Send the email with the verification code
// $subject = 'Your Verification Code';
// $message = 'Please enter the following code to proceed: ' . $verification_code;
// $headers = array('Content-Type: text/html; charset=UTF-8');
// if (!empty($email)) {
// error_log('Sending verification email to ' . $email . ' with code: ' . $verification_code);
// wp_mail($email, $subject, $message, $headers);
// } else {
// error_log('Email address is empty or not set.');
// }
// } else {
// error_log('Checkout method is not "Register". No code sent.');
// }
// } else {
// error_log('Not transitioning from page 4 to page 5.');
// }
// }
// add_action('wp_ajax_verify_email_code', 'verify_email_code');
// add_action('wp_ajax_nopriv_verify_email_code', 'verify_email_code');
// function verify_email_code() {
// session_start();
// // Check the code entered by the user
// $entered_code = sanitize_text_field($_POST['code']);
// $correct_code = isset($_SESSION['verification_code']) ? $_SESSION['verification_code'] : '';
// // Verify if the code matches
// if ($entered_code == $correct_code) {
// unset($_SESSION['verification_code']); // Clear the code from the session
// wp_send_json_success();
// } else {
// wp_send_json_error();
// }
// wp_die();
// }
//Start the session if not already started
//Start the session if not already started
// if (!session_id()) {
// session_start();
// }
// // Send Verification Code
// add_action('wp_ajax_send_verification_code', 'send_verification_code');
// add_action('wp_ajax_nopriv_send_verification_code', 'send_verification_code');
// function send_verification_code() {
// $email = sanitize_email($_POST['email']);
// $code = mt_rand(100000, 999999);
// // Store the code in session
// $_SESSION['verification_code'] = $code;
// // Email subject and message
// $subject = "Your Verification Code";
// $message = "Your verification code is: $code";
// // Add headers for better deliverability
// $headers = array('Content-Type: text/html; charset=UTF-8', 'From: Your Site <[email protected]>');
// // Send the email
// $sent = wp_mail($email, $subject, $message, $headers);
// if ($sent) {
// wp_send_json_success();
// } else {
// wp_send_json_error("Failed to send email"); // Return error if email fails to send
// }
// }
// // Verify Code
// add_action('wp_ajax_verify_email_code', 'verify_email_code');
// add_action('wp_ajax_nopriv_verify_email_code', 'verify_email_code');
// function verify_email_code() {
// $entered_code = $_POST['code'];
// $stored_code = $_SESSION['verification_code']; // Retrieve the stored code from the session
// if ($entered_code == $stored_code) {
// unset($_SESSION['verification_code']); // Clear the code after successful verification
// wp_send_json_success(); // Correct code
// } else {
// wp_send_json_error(); // Incorrect code
// }
// }
// add_action('init', 'test_wp_mail');
// function test_wp_mail() {
// if (isset($_GET['test_email'])) {
// $email_sent = wp_mail("[email protected]", "Test Email", "This is a test email sent from WordPress.");
// if ($email_sent) {
// echo "Test email sent successfully.";
// } else {
// echo "Failed to send test email.";
// }
// exit;
// }
// }
// function enqueue_custom_scripts() {
// wp_enqueue_script('jquery');
// wp_enqueue_script('qondri-theme-script', get_template_directory_uri() . '/assets/js/custom-script.js', array('jquery'), '1.0', true);
// // Localize the script with the AJAX URL
// wp_localize_script('qondri-theme-script', 'ajax_object', array('ajax_url' => admin_url('admin-ajax.php')));
// }
// add_action('wp_enqueue_scripts', 'enqueue_custom_scripts');
// Add this code to your theme's functions.php file or a custom plugin
// Add this code to your theme's functions.php file or a custom plugin
function custom_logout_link_shortcode() {
$logout_url = wp_logout_url(home_url());
$logout_url_without_protocol = preg_replace('#^https?://#', '', $logout_url);
return $logout_url_without_protocol;
}
add_shortcode('logout_link_plain', 'custom_logout_link_shortcode');
function customize_menu_items($items, $args) {
foreach ($items as $key => $item) {
// Replace these with the actual menu item IDs for 'Login', 'Register', and 'Logout'
$login_item_id = 4464; // ID for Login
$register_item_id = 4465; // ID for Register
$logout_item_id = 4466; // ID for Logout
if (is_user_logged_in()) {
// Hide Login and Register links if logged in
if ($item->ID == $login_item_id || $item->ID == $register_item_id) {
unset($items[$key]);
}
// Add a fresh nonce to the logout link
if ($item->ID == $logout_item_id) {
$logout_url = wp_logout_url(home_url());
$nonce = wp_create_nonce('log-out');
$item->url = add_query_arg('_wpnonce', $nonce, $logout_url);
}
} else {
// Hide Logout link if logged out
if ($item->ID == $logout_item_id) {
unset($items[$key]);
}
}
}
return $items;
}
add_filter('wp_nav_menu_objects', 'customize_menu_items', 10, 2);
add_action('wp_footer', function () {
if (is_user_logged_in()) {
$current_user = wp_get_current_user();
$phone = get_user_meta($current_user->ID, 'phone', true); // Fetch phone meta
?>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Fetch logged-in user's data
const userData = {
name: "<?php echo esc_js($current_user->display_name); ?>",
email: "<?php echo esc_js($current_user->user_email); ?>",
phone: "<?php echo esc_js($phone); ?>"
};
// Populate existing Gravity Forms fields by ID
const nameField = document.querySelector("#input_1_86_3");
const emailField = document.querySelector("#input_1_87");
const phoneField = document.querySelector("#input_1_88");
if (nameField) nameField.value = userData.name;
if (emailField) emailField.value = userData.email;
if (phoneField) phoneField.value = userData.phone;
});
</script>
<?php
}
});
add_filter('gform_field_content', function($content, $field, $value, $lead_id, $form_id) {
// Add icons or images based on the field ID
$icon_urls = [
15 => 'https://wedolaundry.uk/wp-content/uploads/2024/12/wash-and-fold.jpg',
19 => 'https://wedolaundry.uk/wp-content/uploads/2024/12/wash-iron.png',
18 => 'https://wedolaundry.uk/wp-content/uploads/2024/12/Dry-Cleaning.png',
16 => 'https://wedolaundry.uk/wp-content/uploads/2024/12/ironing-1.png',
20 => 'https://wedolaundry.uk/wp-content/uploads/2024/12/Clothing-Shoe-Care.png'
];
if (array_key_exists($field->id, $icon_urls)) {
$content = '<label for="input_' . $form_id . '_' . $field->id . '" class="custom-product-title">
<img src="' . esc_url($icon_urls[$field->id]) . '" alt="Label Image for Field ' . $field->id . '" style="max-width:30px; margin-right: 8px;">
' . esc_html($field->label) . '
</label>' . $content;
}
return $content;
}, 10, 5);
add_filter('gform_field_validation_1_61', 'disable_field_61_validation', 10, 4);
function disable_field_61_validation($result, $value, $form, $field) {
// Bypass validation by setting the result to true
$result['is_valid'] = true; // Mark the field as valid
$result['message'] = ''; // Clear any existing validation message
return $result;
}
// add_filter( 'gform_validation_1', function( $validation_result ) {
// $form = $validation_result['form'];
// $form_id = $form['id'];
// // Get the page we’re validating; default to 1 if not present
// $source_page = intval( rgpost( 'gform_source_page_number_' . $form_id ) );
// // Only enforce the £20 minimum when coming *off* page 2
// if ( $source_page === 2 ) {
// // Find the "total" field value
// $total = 0;
// foreach ( $form['fields'] as $field ) {
// if ( $field->type === 'total' ) {
// $raw = rgpost( 'input_' . $field->id );
// $clean = preg_replace( '/[^0-9.]/', '', $raw );
// $total = floatval( $clean );
// break;
// }
// }
// // If under minimum, mark it invalid
// if ( $total < 20 ) {
// $validation_result['is_valid'] = false;
// foreach ( $form['fields'] as &$field ) {
// if ( $field->type === 'total' ) {
// $field->failed_validation = true;
// $field->validation_message = 'Minimum order amount is £20. Please add more items.';
// break;
// }
// }
// $validation_result['form'] = $form;
// }
// }
// return $validation_result;
// } );
// add_filter('gform_stripe_charge_authorized', function($charge, $feed, $entry, $form) {
// if ($form['id'] == 1) {
// // don’t capture yet
// $charge->capture = false;
// gform_update_meta($entry['id'], 'stripe_payment_intent', $charge->payment_intent);
// error_log("Payment authorized (not captured) for entry {$entry['id']}");
// }
// return $charge;
// }, 10, 4);
add_action('gform_approval_approved', function($entry_id, $form_id) {
if ($form_id != 1) return;
// change your approval flag
GFAPI::update_entry_field($entry_id, 'is_approved', '1');
$payment_intent_id = gform_get_meta($entry_id, 'stripe_payment_intent');
if (!$payment_intent_id) {
error_log("No payment intent for entry {$entry_id}");
return;
}
if (!class_exists('\Stripe\Stripe')) {
require_once rtrim(GFStripe::get_plugin_path(), '/') . '/includes/stripe-php/init.php';
}
\Stripe\Stripe::setApiKey(get_option('gf_stripe_api_secret'));
try {
$intent = \Stripe\PaymentIntent::retrieve($payment_intent_id);
if ($intent->status === 'requires_capture') {
$intent->capture();
GFAPI::update_entry_property($entry_id, 'payment_status', 'Paid');
error_log("Captured payment for entry {$entry_id}");
// send your “payment captured” notification
GFAPI::send_notifications(GFAPI::get_form($form_id), GFAPI::get_entry($entry_id), 'payment_captured');
} else {
error_log("Intent status is {$intent->status} (entry {$entry_id})");
}
} catch (Exception $e) {
error_log("Stripe capture error: " . $e->getMessage());
wp_mail(
get_option('admin_email'),
'Payment Capture Failed',
"Failed to capture payment for entry #{$entry_id}: {$e->getMessage()}"
);
}
}, 10, 2);
add_action('gform_after_submission_1', 'send_laundry_thank_you_email', 10, 2);
function send_laundry_thank_you_email($entry, $form) {
$customer_email = rgar($entry, '84'); // Replace '84' with your email field ID
if ($customer_email && is_email($customer_email)) {
$subject = 'Your Laundry Order Confirmation 🧺'; // Fresh + emoji
$message = '
<html>
<body style="font-family: Arial, sans-serif; line-height: 1.6;">
<div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0;">
<h2 style="color: #3498db; text-align: center;">Thanks for Choosing Us!</h2>
<p>Hello,</p>
<p>We’ve received your laundry service request and are already working to make your clothes fresh and clean! 🧼</p>
<h3 style="color: #3498db;">What’s Next?</h3>
<ul>
<li>We’ll review your order details shortly.</li>
<li>Expect a follow-up with pickup/delivery confirmation.</li>
<li>Questions? Reply to this email or call us at [Your Phone Number].</li>
</ul>
<p style="text-align: center;">
<a href="[Your Website URL]"
style="background: #3498db; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; display: inline-block;">
Track Your Order
</a>
</p>
<p>With care,<br>
<strong>The [Your Laundry Name] Team</strong><br>
<small>✨ Making laundry day effortless</small></p>
</div>
</body>
</html>
';
$headers = array('Content-Type: text/html; charset=UTF-8');
wp_mail($customer_email, $subject, $message, $headers);
}
}
add_filter( 'gform_allow_entry_edit', '__return_true' );
//
/**
* Add a custom field for Minimum Order Amount to the Form Settings
* @param array $fields The settings fields
* @param object $form The form object
* @return array
*/
add_filter( 'gform_form_settings_fields', 'add_min_order_form_setting', 10, 2 );
function add_min_order_form_setting( $fields, $form ) {
// Add a new section to the 'Form Settings' tab
$fields['form_options']['fields'][] = array(
'name' => 'minOrderAmount',
'label' => 'Minimum Order Amount',
'tooltip' => 'Prevent form submission if the calculated total is less than this amount.',
'type' => 'text',
'class' => 'small',
'value' => rgar( $form, 'minOrderAmount' ) // Pre-populate the field if a value exists
);
return $fields;
}
/**
* Save the value from our custom form setting
* @param array $form The form object being updated
* @return array
*/
add_filter( 'gform_pre_form_settings_save', 'save_min_order_form_setting' );
function save_min_order_form_setting( $form ) {
// Check if our setting is posted and save it
if ( isset( $_POST['_gform_setting_minOrderAmount'] ) ) {
$form['minOrderAmount'] = abs( floatval( $_POST['_gform_setting_minOrderAmount'] ) );
} else {
// If it's not set, ensure it's removed from the form meta
unset( $form['minOrderAmount'] );
}
return $form;
}
/**
* Validate Minimum Order Amount for Gravity Forms using the form setting
*/
// add_filter( 'gform_validation', 'validate_minimum_order_from_setting', 10, 2 );
function validate_minimum_order_from_setting( $validation_result ) {
$form = $validation_result['form'];
// 1. Check if this form even has a minimum amount set. If not, bail.
if ( empty( $form['minOrderAmount'] ) ) {
return $validation_result;
}
$minimum_amount = floatval( $form['minOrderAmount'] );
// 2. Get the total from the submitted form
$total = GFCommon::get_order_total( $form, $_POST );
// 3. Check if the total is less than the minimum
if ( $total < $minimum_amount ) {
// Mark the form as invalid
$validation_result['is_valid'] = false;
// Find the Total field so we can highlight it
foreach( $form['fields'] as &$field ) {
// Check if this field is the total field
if ( $field->type == 'total' ) {
$field->failed_validation = true;
$field->validation_message = 'Sorry, the minimum order amount is ' . gf_apply_filters( array( 'gform_currency', $form['id'] ), '$' ) . number_format( $minimum_amount, 2 ) . '. Please add more items to your order.';
break;
}
}
// Assign our modified $form object back to the validation result
$validation_result['form'] = $form;
}
return $validation_result;
}
add_filter( 'gravityview/edit_entry/hide-product-fields', '__return_false' );
add_action('gform_after_submission', function($entry, $form) {
if ((int) $form['id'] === 1) {
$total = rgar($entry, '61');
$paid = $total;
$remaining = $total - $paid;
GFAPI::update_entry_field($entry['id'], '340', $paid);
GFAPI::update_entry_field($entry['id'], '341', $remaining);
}
}, 10, 2);
// add_action('gform_after_update_entry', function($form, $entry_id) {
// $entry = GFAPI::get_entry($entry_id);
// $total = rgar($entry, '61');
// $paid = rgar($entry, '340');
// $remaining = $total - $paid;
// GFAPI::update_entry_field($entry_id, '342', $remaining);
// }, 10, 2);
add_action('gravityview/edit_entry/after_update', function($form, $entry_id) {
// Always re-fetch the entry after GV saves changes
$entry = GFAPI::get_entry($entry_id);
if (is_wp_error($entry)) {
return;
}
$total = floatval(rgar($entry, '61'));
$paid = floatval(rgar($entry, '340'));
// Ensure defaults
if (empty($total)) { $total = 0; }
if (empty($paid)) { $paid = 0; }
$remaining = $total - $paid;
GFAPI::update_entry_field($entry_id, '341', $remaining);
}, 20, 2);
add_action('gform_after_update_entry','update_payment_fields_after_update', 10, 2);
function update_payment_fields_after_update($form, $entry_id) {
// Get the updated entry
$entry = GFAPI::get_entry($entry_id);
if (is_wp_error($entry)) {
error_log('Error getting entry: ' . $entry->get_error_message());
return;
}
$total = rgar($entry, '61');
$paid = rgar($entry, '340');
// Make sure we have valid values
if (empty($total)) $total = 0;
if (empty($paid)) $paid = 0;
$remaining = $total - $paid;
// Update the remaining balance field
$result = GFAPI::update_entry_field($entry_id, '341', $remaining);
if (is_wp_error($result)) {
error_log('Error updating entry field: ' . $result->get_error_message());
}
}
// Add custom column header
add_filter('gform_entries_column_filter', function($value, $form_id, $field_id, $entry) {
// Create a new "Pay Now" column (we'll use fake field ID 'pay_link')
if ($form_id == 1 && $field_id === 'pay_link') {
$remaining = rgar($entry, '341');
if ($remaining > 0) {
$pay_link = site_url('/remaining-payment-form/?entry_id=' . $entry['id']);
return '<a href="' . esc_url($pay_link) . '" target="_blank" style="color: #fff; background:#0073aa; padding:6px 8px; border-radius:4px; text-decoration:none;">Pay Now</a>';
}
}
return $value;
}, 10, 4);
// Register the custom column with label
add_filter('gform_entry_list_columns', function($columns, $form_id) {
if ($form_id == 1) {
$columns['pay_link'] = __('Payment Link', 'your-textdomain'); // New column header
}
return $columns;
}, 10, 2);
// Auto-populate Remaining Payment Form (ID = 6)
add_filter('gform_pre_render_5', 'populate_remaining_balance_form');
add_filter('gform_pre_validation_5', 'populate_remaining_balance_form');
add_filter('gform_pre_submission_filter_5', 'populate_remaining_balance_form');
add_filter('gform_admin_pre_render_5', 'populate_remaining_balance_form');
function populate_remaining_balance_form($form) {
$entry_id = isset($_GET['entry_id']) ? absint($_GET['entry_id']) : 0;
if ($entry_id) {
$entry = GFAPI::get_entry($entry_id);
if (!is_wp_error($entry)) {
$remaining = rgar($entry, '341'); // Remaining Balance field in the original order
if (empty($remaining)) {
$remaining = 0;
}
foreach ($form['fields'] as &$field) {
// Target product field ID 18 in form 6
if ($field->id == 6 && $field->type == 'product') {
// ✅ Correct way: set both basePrice and defaultValue
$field->basePrice = $remaining;
$field->defaultValue = $remaining;
// Lock quantity at 1
$field->disableQuantity = true;
// Update the label
$field->label = "Remaining Balance:" . number_format($remaining, 2);
}
// Pass entry_id hidden field
if ($field->type == 'hidden' && $field->adminLabel == 'entry_id') {
$field->defaultValue = $entry_id;
}
}
}
}
return $form;
}
add_action('gform_after_submission_5', 'process_remaining_payment', 10, 2);
function process_remaining_payment($entry, $form) {
$original_entry_id = rgpost('entry_id') ?: (isset($_GET['entry_id']) ? absint($_GET['entry_id']) : 0);
if ($original_entry_id) {
$original_entry = GFAPI::get_entry($original_entry_id);
if (!is_wp_error($original_entry)) {
$already_paid = floatval(rgar($original_entry, '340')); // Paid field
$total_amount = floatval(rgar($original_entry, '61')); // Total field
// ✅ Correct: get product price from input 18.2
$payment_amount_raw = rgar($entry, '6.2');
$payment_amount = floatval(preg_replace('/[^0-9.\-]/', '', $payment_amount_raw));
// Calculate new totals
$new_paid = $already_paid + $payment_amount;
$new_remaining = $total_amount - $new_paid;
if ($new_remaining < 0) {
$new_paid = $total_amount;
$new_remaining = 0;
}
GFAPI::update_entry_field($original_entry_id, '340', $new_paid);
GFAPI::update_entry_field($original_entry_id, '341', $new_remaining);
$note = sprintf(
'Payment of £%s received. Paid: £%s | Remaining: £%s',
number_format($payment_amount, 2),
number_format($new_paid, 2),
number_format($new_remaining, 2)
);
GFAPI::add_note($original_entry_id, 0, 'System', $note);
}
}
}
// Add custom CSS for the payment form
// add_action('wp_head', function() {
// if (isset($_GET['entry_id'])) {
// echo '<style>
// .gform_wrapper .ginput_container_product .ginput_product_price_label {
// font-weight: bold;
// font-size: 1.2em;
// color: #333;
// }
// .remaining-balance-notice {
// background: #f8f8f8;
// padding: 15px;
// border-left: 4px solid #0073aa;
// margin-bottom: 20px;
// }
// </style>';
// }
// });
// Add a notice to the payment form
add_filter('gform_pre_render_5', 'add_payment_form_notice', 10, 1);
function add_payment_form_notice($form) {
$entry_id = isset($_GET['entry_id']) ? absint($_GET['entry_id']) : 0;
if ($entry_id) {
$entry = GFAPI::get_entry($entry_id);
if (!is_wp_error($entry)) {
// Safely convert values to float (default 0 if empty)
$order_total = floatval(rgar($entry, '61')) ?: 0;
$already_paid = floatval(rgar($entry, '340')) ?: 0;
$remaining = floatval(rgar($entry, '341')) ?: 0;
// Add a custom message at the top of the form
$message = '<div class="remaining-balance-notice">';
$message .= '<h3>Payment for Order #' . $entry_id . '</h3>';
$message .= '<p>Order Total: <strong>£' . number_format($order_total, 2) . '</strong></p>';
$message .= '<p>Already Paid: <strong>£' . number_format($already_paid, 2) . '</strong></p>';
$message .= '<p>Remaining Balance: <strong>£' . number_format($remaining, 2) . '</strong></p>';
$message .= '</div>';
// Prepend the message to the form description
$form['description'] = $message . $form['description'];
}
}
return $form;
}
// Use JavaScript to ensure the product price is displayed correctly
add_action('gform_register_init_scripts', 'fix_product_price_display', 10, 2);
function fix_product_price_display($form) {
if ($form['id'] == 5) { // Only for form ID 6
$script = "
jQuery(document).ready(function($) {
// Check if we have a product field
var productField = $('.gfield_product_price');
if (productField.length) {
// Force update the product price display
setTimeout(function() {
var price = productField.data('price');
if (price && price > 0) {
productField.text('$' + parseFloat(price).toFixed(2));
}
}, 500);
}
// Also update any hidden inputs that might contain the price
$('input[type=hidden][id*=\"input_\"]').each(function() {
var id = $(this).attr('id');
if (id.indexOf('_3_') !== -1 && id.indexOf('_1') !== -1) {
var val = $(this).val();
if (val && parseFloat(val) > 0) {
$(this).val(parseFloat(val).toFixed(2));
}
}
});
});
";
GFFormDisplay::add_init_script($form['id'], 'fix_product_price', GFFormDisplay::ON_PAGE_RENDER, $script);
}
}
// Alternative population function
add_filter('gform_field_value', 'populate_product_price', 10, 3);
function populate_product_price($value, $field, $name) {
if ($field->formId == 5 && $field->id == 6 && $field->type == 'product') {
$entry_id = isset($_GET['entry_id']) ? absint($_GET['entry_id']) : 0;
if ($entry_id) {
$entry = GFAPI::get_entry($entry_id);
if (!is_wp_error($entry)) {
$remaining = rgar($entry, '341');
if ($remaining > 0) {
return $remaining;
}
}
}
}
return $value;
}
// Run AFTER payment is confirmed
add_action('gform_post_payment_completed', 'update_parent_after_remaining_payment', 10, 2);
function update_parent_after_remaining_payment($entry, $action) {
// Only run for your Remaining Payment Form (ID = 6)
if ((int) $entry['form_id'] !== 5) {
return;
}
// Get original entry ID from hidden field
$original_entry_id = rgar($entry, 'entry_id');
if (!$original_entry_id) {
return;
}
$original_entry = GFAPI::get_entry($original_entry_id);
if (is_wp_error($original_entry)) {
return;
}
// Pull values
$already_paid = floatval(rgar($original_entry, '340')); // Paid
$total_amount = floatval(rgar($original_entry, '61')); // Total
$payment_amount = floatval($action['amount']); // ✅ Reliable paid amount from Stripe/PayPal
// Calculate
$new_paid = $already_paid + $payment_amount;
$new_remaining = max(0, $total_amount - $new_paid);
// Update parent entry
GFAPI::update_entry_field($original_entry_id, '340', $new_paid);
GFAPI::update_entry_field($original_entry_id, '341', $new_remaining);
// Add a note
$note = sprintf(
'Remaining payment of £%s received. New paid total: £%s. Remaining balance: £%s',
number_format($payment_amount, 2),
number_format($new_paid, 2),
number_format($new_remaining, 2)
);
GFAPI::add_note($original_entry_id, 0, 'System', $note);
}
add_filter('gform_pre_render_5', 'hide_remaining_balance_form');
add_filter('gform_pre_validation_5', 'hide_remaining_balance_form');
function hide_remaining_balance_form($form) {
$entry_id = isset($_GET['entry_id']) ? absint($_GET['entry_id']) : 0;
if ($entry_id) {
$entry = GFAPI::get_entry($entry_id);
if (!is_wp_error($entry)) {
$remaining = floatval(rgar($entry, '341')); // Remaining Balance field from Form 1
if ($remaining <= 0) {
// Replace the form markup with a simple message
echo '<p class="payment-already-done" style="padding:20px; font-size:16px; color:green; background:#f1f1f1; border-radius:4px;">
✅ Your payment is already complete. No remaining balance.
</p>';
return false; // stops the form from rendering
}
}
}
return $form;
}
// Dequeue default Stripe script and reload with cfasync attribute
add_action('wp_enqueue_scripts', 'fix_stripe_rocket_loader', 999);
function fix_stripe_rocket_loader() {
// Remove the default Stripe script
wp_dequeue_script('stripe-js');
wp_deregister_script('stripe-js');
// Re-register with data-cfasync attribute
wp_register_script(
'stripe-js',
'https://js.stripe.com/v3/',
[],
null,
true
);
// Add data-cfasync attribute
add_filter('script_loader_tag', 'add_cfasync_attribute', 10, 2);
}
function add_cfasync_attribute($tag, $handle) {
if ($handle === 'stripe-js') {
// Replace the entire script tag to add data-cfasync
$tag = '<script data-cfasync="false" src="https://js.stripe.com/v3/"></script>';
}
return $tag;
}
// Completely handle Stripe loading for Gravity Forms
add_action('wp_head', 'prevent_stripe_rocket_loader');
function prevent_stripe_rocket_loader() {
if (!class_exists('GFStripe')) return;
// Get all forms that might use Stripe
$forms = GFFormsModel::get_forms();
$stripe_forms = [];
foreach ($forms as $form) {
$feeds = GFAPI::get_feeds(null, $form->id, 'gravityformsstripe');
if (!empty($feeds)) {
$stripe_forms[] = $form->id;
}
}
// If current page has a Stripe form, add meta tag
if (!empty($stripe_forms)) {
echo '<meta name="cf-ignore-rocket-loader" content="stripe-scripts">';
}
}