39339-vm/wp-content/mu-plugins/coaching-mvp.php.bak-20260324
2026-03-24 10:38:28 +00:00

843 lines
30 KiB
Plaintext

<?php
/**
* Plugin Name: Coaching MVP Site Kit
* Description: Registers testimonials, bookings, and lead capture workflow plus frontend styles for the coaching MVP.
*/
if (!defined('ABSPATH')) {
exit;
}
function coaching_mvp_services() {
return [
'discovery-call' => 'Discovery Call',
'clarity-session' => 'Clarity Session',
'momentum-coaching' => 'Momentum Coaching',
'leadership-intensives' => 'Leadership Intensive',
];
}
function coaching_mvp_register_post_types() {
register_post_type('testimonial', [
'labels' => [
'name' => 'Testimonials',
'singular_name' => 'Testimonial',
'add_new_item' => 'Add New Testimonial',
'edit_item' => 'Edit Testimonial',
],
'public' => true,
'show_in_rest' => true,
'menu_icon' => 'dashicons-format-quote',
'supports' => ['title', 'editor', 'excerpt'],
'has_archive' => false,
'rewrite' => ['slug' => 'testimonial'],
]);
register_post_type('booking_request', [
'labels' => [
'name' => 'Bookings',
'singular_name' => 'Booking',
'add_new_item' => 'Add Booking',
'edit_item' => 'View Booking',
],
'public' => false,
'show_ui' => true,
'show_in_rest' => false,
'menu_icon' => 'dashicons-calendar-alt',
'supports' => ['title'],
'capability_type' => 'post',
'map_meta_cap' => true,
]);
register_post_type('lead_capture', [
'labels' => [
'name' => 'Leads',
'singular_name' => 'Lead',
'add_new_item' => 'Add Lead',
'edit_item' => 'View Lead',
],
'public' => false,
'show_ui' => true,
'show_in_rest' => false,
'menu_icon' => 'dashicons-email-alt2',
'supports' => ['title'],
'capability_type' => 'post',
'map_meta_cap' => true,
]);
}
add_action('init', 'coaching_mvp_register_post_types');
function coaching_mvp_body_class($classes) {
$classes[] = 'coaching-mvp-active';
return $classes;
}
add_filter('body_class', 'coaching_mvp_body_class');
function coaching_mvp_styles() {
if (is_admin()) {
return;
}
wp_register_style('coaching-mvp-inline', false, [], null);
wp_enqueue_style('coaching-mvp-inline');
$css = <<<'CSS'
:root {
--coach-primary: #5b6cff;
--coach-secondary: #16c4b5;
--coach-background: #f4f7ff;
--coach-surface: #ffffff;
--coach-text: #172033;
--coach-muted: #5f6b84;
--coach-border: rgba(23,32,51,.08);
--coach-shadow: 0 30px 70px rgba(32,45,91,.14);
--coach-radius: 24px;
--coach-radius-sm: 16px;
--coach-spacing: 1.5rem;
}
body.coaching-mvp-active {
background: linear-gradient(180deg, #eef3ff 0%, #f9fbff 32%, #ffffff 100%);
color: var(--coach-text);
}
body.coaching-mvp-active .wp-site-blocks,
body.coaching-mvp-active .site,
body.coaching-mvp-active main {
color: var(--coach-text);
}
body.coaching-mvp-active.page .wp-site-blocks main,
body.coaching-mvp-active.home .wp-site-blocks main,
body.coaching-mvp-active.blog .wp-site-blocks main {
--wp--style--global--content-size: min(1180px, calc(100vw - 48px));
--wp--style--global--wide-size: min(1320px, calc(100vw - 48px));
}
body.coaching-mvp-active.page .wp-block-post-content,
body.coaching-mvp-active.home .wp-block-post-content,
body.coaching-mvp-active.blog .wp-block-post-content {
width: 100%;
}
body.coaching-mvp-active .wp-block-post-content.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)),
body.coaching-mvp-active .coach-home-page.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
max-width: var(--wp--style--global--content-size);
}
.coach-hero,
.coach-section,
.coach-panel,
.coach-form-wrap,
.coach-service-card,
.coach-testimonial-card,
.coach-stat,
.coach-process-card,
.coach-mini-card,
.coach-faq-card,
.coach-story-card {
border-radius: var(--coach-radius);
}
.coach-hero {
padding: clamp(2rem, 5vw, 4rem);
background:
radial-gradient(circle at top right, rgba(22,196,181,.28), transparent 28%),
radial-gradient(circle at bottom left, rgba(91,108,255,.20), transparent 32%),
linear-gradient(135deg, #101a3a 0%, #213872 48%, #5b6cff 100%);
box-shadow: var(--coach-shadow);
overflow: hidden;
}
.coach-hero h1,
.coach-hero p,
.coach-hero li,
.coach-hero strong {
color: #fff;
}
.coach-eyebrow {
display: inline-flex;
align-items: center;
gap: .5rem;
padding: .45rem .9rem;
border-radius: 999px;
background: rgba(255,255,255,.12);
border: 1px solid rgba(255,255,255,.18);
font-size: .82rem;
letter-spacing: .06em;
text-transform: uppercase;
}
.coach-hero .wp-block-buttons .wp-block-button__link,
.coach-cta-row .wp-block-button__link,
.coach-form-wrap button,
.coach-inline-link {
border-radius: 999px;
padding: .95rem 1.4rem;
font-weight: 700;
text-decoration: none;
}
.coach-hero .is-style-outline > .wp-block-button__link {
border: 1px solid rgba(255,255,255,.45);
color: #fff;
background: transparent;
}
.coach-grid-2,
.coach-grid-3,
.coach-grid-4,
.coach-card-grid,
.coach-testimonial-grid,
.coach-process-grid,
.coach-story-grid,
.coach-faq-grid,
.coach-stats-grid,
.coach-mini-grid {
display: grid;
gap: 1.2rem;
}
.coach-grid-2 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.coach-grid-3,
.coach-card-grid,
.coach-testimonial-grid,
.coach-process-grid,
.coach-story-grid,
.coach-faq-grid,
.coach-mini-grid { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.coach-grid-4,
.coach-stats-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.coach-panel,
.coach-service-card,
.coach-testimonial-card,
.coach-stat,
.coach-process-card,
.coach-mini-card,
.coach-faq-card,
.coach-story-card,
.coach-form-wrap {
background: rgba(255,255,255,.92);
border: 1px solid var(--coach-border);
box-shadow: var(--coach-shadow);
padding: 1.35rem;
}
.coach-panel.soft {
background: rgba(255,255,255,.10);
border-color: rgba(255,255,255,.16);
}
.coach-stat strong {
display: block;
font-size: clamp(1.45rem, 3vw, 2.1rem);
color: var(--coach-text);
}
.coach-stat span,
.coach-muted,
.coach-service-card p,
.coach-process-card p,
.coach-faq-card p,
.coach-story-card p,
.coach-testimonial-meta,
.coach-form-wrap p,
.coach-section p {
color: var(--coach-muted);
}
.coach-badge {
display: inline-flex;
align-items: center;
gap: .45rem;
padding: .4rem .8rem;
border-radius: 999px;
background: rgba(91,108,255,.10);
color: var(--coach-primary);
font-size: .85rem;
font-weight: 700;
}
.coach-service-card h3,
.coach-process-card h3,
.coach-faq-card h3,
.coach-story-card h3,
.coach-testimonial-card h3,
.coach-mini-card h3 {
margin-top: .35rem;
margin-bottom: .55rem;
}
.coach-service-card ul,
.coach-process-card ul,
.coach-story-card ul {
margin: .8rem 0 0 1rem;
}
.coach-icon-dot {
width: 2.25rem;
height: 2.25rem;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: rgba(91,108,255,.12);
color: var(--coach-primary);
font-weight: 800;
}
.coach-form-wrap {
padding: 1.5rem;
}
.coach-form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1rem;
}
.coach-form-grid .full {
grid-column: 1 / -1;
}
.coach-form-wrap label {
display: block;
font-weight: 700;
margin-bottom: .4rem;
color: var(--coach-text);
}
.coach-form-wrap input,
.coach-form-wrap textarea,
.coach-form-wrap select {
width: 100%;
border: 1px solid rgba(23,32,51,.12);
border-radius: 16px;
padding: .9rem 1rem;
font-size: 1rem;
background: #fff;
color: var(--coach-text);
}
.coach-form-wrap textarea {
min-height: 140px;
}
.coach-form-wrap button {
border: 0;
background: linear-gradient(135deg, var(--coach-primary), #7f56d9);
color: #fff;
cursor: pointer;
box-shadow: 0 12px 24px rgba(91,108,255,.25);
}
.coach-alert {
border-radius: 16px;
padding: .95rem 1rem;
margin-bottom: 1rem;
font-weight: 600;
}
.coach-alert.success {
background: rgba(22,196,181,.12);
color: #116c63;
border: 1px solid rgba(22,196,181,.18);
}
.coach-alert.error {
background: rgba(255,107,129,.10);
color: #8d2d3b;
border: 1px solid rgba(255,107,129,.18);
}
.coach-testimonial-grid blockquote {
margin: 0;
}
.coach-testimonial-card .coach-rating {
color: #f5a524;
letter-spacing: .18em;
font-size: .95rem;
}
.coach-cta-band {
padding: 1.5rem;
background: linear-gradient(135deg, rgba(91,108,255,.12), rgba(22,196,181,.12));
border: 1px solid rgba(91,108,255,.12);
border-radius: var(--coach-radius);
}
.coach-stack > * + * {
margin-top: 1rem;
}
.coach-section {
margin-top: clamp(1.4rem, 4vw, 2.5rem);
}
.coach-home-page .wp-block-post-title,
.page-slug-home .wp-block-post-title {
display: none;
}
.coach-inline-link {
color: var(--coach-primary);
background: rgba(91,108,255,.08);
}
.coach-admin-link {
display: inline-flex;
align-items: center;
gap: .5rem;
margin-top: .6rem;
color: var(--coach-primary);
text-decoration: none;
font-weight: 700;
}
.coach-footer-note {
text-align: center;
color: var(--coach-muted);
font-size: .95rem;
}
@media (max-width: 781px) {
.coach-hero { padding: 1.5rem; }
}
CSS;
wp_add_inline_style('coaching-mvp-inline', $css);
}
add_action('wp_enqueue_scripts', 'coaching_mvp_styles');
function coaching_mvp_sanitize_textarea($value) {
return trim(wp_strip_all_tags((string) $value));
}
function coaching_mvp_handle_forms() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_POST['coaching_form_action'])) {
return;
}
$action = sanitize_key(wp_unslash($_POST['coaching_form_action']));
$redirect = !empty($_POST['_wp_http_referer']) ? wp_unslash($_POST['_wp_http_referer']) : home_url('/');
$redirect = remove_query_arg(['booking_status', 'lead_status'], $redirect);
if (!isset($_POST['coaching_form_nonce']) || !wp_verify_nonce(wp_unslash($_POST['coaching_form_nonce']), 'coaching_form_submit')) {
wp_safe_redirect(add_query_arg($action === 'booking' ? 'booking_status' : 'lead_status', 'error', $redirect));
exit;
}
$name = sanitize_text_field(wp_unslash($_POST['name'] ?? ''));
$email = sanitize_email(wp_unslash($_POST['email'] ?? ''));
$phone = sanitize_text_field(wp_unslash($_POST['phone'] ?? ''));
$message = coaching_mvp_sanitize_textarea(wp_unslash($_POST['message'] ?? ''));
if (!$name || !$email) {
wp_safe_redirect(add_query_arg($action === 'booking' ? 'booking_status' : 'lead_status', 'error', $redirect));
exit;
}
if ($action === 'booking') {
$service = sanitize_text_field(wp_unslash($_POST['service'] ?? 'Discovery Call'));
$preferred_date = sanitize_text_field(wp_unslash($_POST['preferred_date'] ?? ''));
$preferred_time = sanitize_text_field(wp_unslash($_POST['preferred_time'] ?? ''));
$format = sanitize_text_field(wp_unslash($_POST['session_format'] ?? 'Zoom'));
$goal = coaching_mvp_sanitize_textarea(wp_unslash($_POST['goal'] ?? ''));
$post_id = wp_insert_post([
'post_type' => 'booking_request',
'post_status' => 'private',
'post_title' => sprintf('%s — %s', $name, $preferred_date ?: current_time('Y-m-d')),
], true);
if (is_wp_error($post_id)) {
wp_safe_redirect(add_query_arg('booking_status', 'error', $redirect));
exit;
}
update_post_meta($post_id, '_booking_name', $name);
update_post_meta($post_id, '_booking_email', $email);
update_post_meta($post_id, '_booking_phone', $phone);
update_post_meta($post_id, '_booking_service', $service);
update_post_meta($post_id, '_booking_date', $preferred_date);
update_post_meta($post_id, '_booking_time', $preferred_time);
update_post_meta($post_id, '_booking_format', $format);
update_post_meta($post_id, '_booking_goal', $goal);
update_post_meta($post_id, '_booking_message', $message);
wp_safe_redirect(add_query_arg('booking_status', 'success', $redirect));
exit;
}
if ($action === 'lead') {
$focus = sanitize_text_field(wp_unslash($_POST['focus'] ?? ''));
$company = sanitize_text_field(wp_unslash($_POST['company'] ?? ''));
$post_id = wp_insert_post([
'post_type' => 'lead_capture',
'post_status' => 'private',
'post_title' => sprintf('%s — %s', $name, current_time('Y-m-d H:i')),
], true);
if (is_wp_error($post_id)) {
wp_safe_redirect(add_query_arg('lead_status', 'error', $redirect));
exit;
}
update_post_meta($post_id, '_lead_name', $name);
update_post_meta($post_id, '_lead_email', $email);
update_post_meta($post_id, '_lead_phone', $phone);
update_post_meta($post_id, '_lead_company', $company);
update_post_meta($post_id, '_lead_focus', $focus);
update_post_meta($post_id, '_lead_message', $message);
wp_safe_redirect(add_query_arg('lead_status', 'success', $redirect));
exit;
}
}
add_action('init', 'coaching_mvp_handle_forms', 20);
function coaching_mvp_booking_form_shortcode() {
$status = isset($_GET['booking_status']) ? sanitize_key(wp_unslash($_GET['booking_status'])) : '';
ob_start();
?>
<div class="coach-form-wrap" id="book-form">
<?php if ($status === 'success') : ?>
<div class="coach-alert success">Thanks — your booking request was received. You can review it anytime in the WordPress admin under Bookings.</div>
<?php elseif ($status === 'error') : ?>
<div class="coach-alert error">Please complete the required fields and try again.</div>
<?php endif; ?>
<div class="coach-stack">
<div>
<span class="coach-badge">Book a pay-later session</span>
<h3>Request your coaching session</h3>
<p>Pick the service, preferred date, and format. This MVP stores requests in WordPress so the coach can confirm details personally.</p>
</div>
<form method="post" class="coach-stack">
<?php wp_nonce_field('coaching_form_submit', 'coaching_form_nonce'); ?>
<input type="hidden" name="coaching_form_action" value="booking" />
<div class="coach-form-grid">
<div>
<label for="coach-book-name">Full name</label>
<input id="coach-book-name" type="text" name="name" required />
</div>
<div>
<label for="coach-book-email">Email</label>
<input id="coach-book-email" type="email" name="email" required />
</div>
<div>
<label for="coach-book-phone">Phone</label>
<input id="coach-book-phone" type="text" name="phone" />
</div>
<div>
<label for="coach-book-service">Service</label>
<select id="coach-book-service" name="service">
<?php foreach (coaching_mvp_services() as $value => $label) : ?>
<option value="<?php echo esc_attr($label); ?>"><?php echo esc_html($label); ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="coach-book-date">Preferred date</label>
<input id="coach-book-date" type="date" name="preferred_date" required />
</div>
<div>
<label for="coach-book-time">Preferred time</label>
<input id="coach-book-time" type="time" name="preferred_time" required />
</div>
<div>
<label for="coach-book-format">Session format</label>
<select id="coach-book-format" name="session_format">
<option value="Zoom">Zoom</option>
<option value="Phone">Phone</option>
<option value="In Person">In Person</option>
</select>
</div>
<div class="full">
<label for="coach-book-goal">What would you like help with?</label>
<textarea id="coach-book-goal" name="goal" placeholder="Share the goal, transition, challenge, or outcome you want to focus on."></textarea>
</div>
<div class="full">
<label for="coach-book-message">Anything else?</label>
<textarea id="coach-book-message" name="message" placeholder="Include timing constraints, preferred cadence, or context."></textarea>
</div>
</div>
<div>
<button type="submit">Request Session</button>
</div>
</form>
</div>
</div>
<?php
return ob_get_clean();
}
add_shortcode('coaching_booking_form', 'coaching_mvp_booking_form_shortcode');
function coaching_mvp_lead_form_shortcode() {
$status = isset($_GET['lead_status']) ? sanitize_key(wp_unslash($_GET['lead_status'])) : '';
ob_start();
?>
<div class="coach-form-wrap" id="lead-form">
<?php if ($status === 'success') : ?>
<div class="coach-alert success">Thanks — your message was captured and is now visible in the WordPress admin under Leads.</div>
<?php elseif ($status === 'error') : ?>
<div class="coach-alert error">Please add your name and email so we can respond properly.</div>
<?php endif; ?>
<div class="coach-stack">
<div>
<span class="coach-badge">Lead capture</span>
<h3>Start the conversation</h3>
<p>Not ready to book yet? Share your focus area and the coach can follow up with the right next step.</p>
</div>
<form method="post" class="coach-stack">
<?php wp_nonce_field('coaching_form_submit', 'coaching_form_nonce'); ?>
<input type="hidden" name="coaching_form_action" value="lead" />
<div class="coach-form-grid">
<div>
<label for="coach-lead-name">Full name</label>
<input id="coach-lead-name" type="text" name="name" required />
</div>
<div>
<label for="coach-lead-email">Email</label>
<input id="coach-lead-email" type="email" name="email" required />
</div>
<div>
<label for="coach-lead-phone">Phone</label>
<input id="coach-lead-phone" type="text" name="phone" />
</div>
<div>
<label for="coach-lead-company">Company / role</label>
<input id="coach-lead-company" type="text" name="company" />
</div>
<div class="full">
<label for="coach-lead-focus">What are you working toward?</label>
<input id="coach-lead-focus" type="text" name="focus" placeholder="Examples: career transition, executive presence, consistency, burnout recovery" />
</div>
<div class="full">
<label for="coach-lead-message">Message</label>
<textarea id="coach-lead-message" name="message" placeholder="Share what support would feel most valuable right now."></textarea>
</div>
</div>
<div>
<button type="submit">Send Inquiry</button>
</div>
</form>
</div>
</div>
<?php
return ob_get_clean();
}
add_shortcode('coaching_lead_form', 'coaching_mvp_lead_form_shortcode');
function coaching_mvp_testimonials_shortcode($atts = []) {
$atts = shortcode_atts(['limit' => 6], $atts, 'coaching_testimonials');
$items = get_posts([
'post_type' => 'testimonial',
'post_status' => 'publish',
'numberposts' => (int) $atts['limit'],
'orderby' => 'menu_order date',
'order' => 'ASC',
]);
if (!$items) {
return '<p>No testimonials yet.</p>';
}
ob_start();
echo '<div class="coach-testimonial-grid">';
foreach ($items as $item) {
$role = get_post_meta($item->ID, '_testimonial_role', true);
echo '<article class="coach-testimonial-card">';
echo '<div class="coach-rating">★★★★★</div>';
echo '<blockquote><p>' . esc_html(wp_strip_all_tags($item->post_content)) . '</p></blockquote>';
echo '<h3>' . esc_html(get_the_title($item)) . '</h3>';
if ($role) {
echo '<div class="coach-testimonial-meta">' . esc_html($role) . '</div>';
}
echo '</article>';
}
echo '</div>';
return ob_get_clean();
}
add_shortcode('coaching_testimonials', 'coaching_mvp_testimonials_shortcode');
function coaching_mvp_admin_columns($columns, $post_type) {
if ($post_type === 'booking_request') {
return [
'cb' => $columns['cb'],
'title' => 'Booking',
'service' => 'Service',
'date' => 'Date',
'contact' => 'Contact',
'format' => 'Format',
];
}
if ($post_type === 'lead_capture') {
return [
'cb' => $columns['cb'],
'title' => 'Lead',
'focus' => 'Focus',
'contact' => 'Contact',
'date' => 'Received',
];
}
if ($post_type === 'testimonial') {
$columns['role'] = 'Role';
return $columns;
}
return $columns;
}
add_filter('manage_booking_request_posts_columns', fn($columns) => coaching_mvp_admin_columns($columns, 'booking_request'));
add_filter('manage_lead_capture_posts_columns', fn($columns) => coaching_mvp_admin_columns($columns, 'lead_capture'));
add_filter('manage_testimonial_posts_columns', fn($columns) => coaching_mvp_admin_columns($columns, 'testimonial'));
function coaching_mvp_render_admin_column($column, $post_id) {
switch ($column) {
case 'service':
echo esc_html((string) get_post_meta($post_id, '_booking_service', true));
break;
case 'date':
if (get_post_type($post_id) === 'booking_request') {
$date = get_post_meta($post_id, '_booking_date', true);
$time = get_post_meta($post_id, '_booking_time', true);
echo esc_html(trim($date . ' ' . $time));
} else {
echo esc_html(get_the_date('Y-m-d H:i', $post_id));
}
break;
case 'contact':
$email_key = get_post_type($post_id) === 'booking_request' ? '_booking_email' : '_lead_email';
$phone_key = get_post_type($post_id) === 'booking_request' ? '_booking_phone' : '_lead_phone';
echo esc_html((string) get_post_meta($post_id, $email_key, true));
$phone = get_post_meta($post_id, $phone_key, true);
if ($phone) {
echo '<br>' . esc_html((string) $phone);
}
break;
case 'format':
echo esc_html((string) get_post_meta($post_id, '_booking_format', true));
break;
case 'focus':
echo esc_html((string) get_post_meta($post_id, '_lead_focus', true));
break;
case 'role':
echo esc_html((string) get_post_meta($post_id, '_testimonial_role', true));
break;
}
}
add_action('manage_booking_request_posts_custom_column', 'coaching_mvp_render_admin_column', 10, 2);
add_action('manage_lead_capture_posts_custom_column', 'coaching_mvp_render_admin_column', 10, 2);
add_action('manage_testimonial_posts_custom_column', 'coaching_mvp_render_admin_column', 10, 2);
function coaching_mvp_details_meta_box() {
foreach (['booking_request', 'lead_capture'] as $post_type) {
add_meta_box('coaching-mvp-details', 'Submission Details', 'coaching_mvp_details_meta_box_html', $post_type, 'normal', 'high');
}
add_meta_box('coaching-mvp-testimonial-role', 'Testimonial Details', 'coaching_mvp_testimonial_meta_box_html', 'testimonial', 'side');
}
add_action('add_meta_boxes', 'coaching_mvp_details_meta_box');
function coaching_mvp_details_meta_box_html($post) {
if ($post->post_type === 'booking_request') {
$fields = [
'Name' => get_post_meta($post->ID, '_booking_name', true),
'Email' => get_post_meta($post->ID, '_booking_email', true),
'Phone' => get_post_meta($post->ID, '_booking_phone', true),
'Service' => get_post_meta($post->ID, '_booking_service', true),
'Preferred date' => get_post_meta($post->ID, '_booking_date', true),
'Preferred time' => get_post_meta($post->ID, '_booking_time', true),
'Format' => get_post_meta($post->ID, '_booking_format', true),
'Goal' => get_post_meta($post->ID, '_booking_goal', true),
'Extra notes' => get_post_meta($post->ID, '_booking_message', true),
];
} else {
$fields = [
'Name' => get_post_meta($post->ID, '_lead_name', true),
'Email' => get_post_meta($post->ID, '_lead_email', true),
'Phone' => get_post_meta($post->ID, '_lead_phone', true),
'Company / role' => get_post_meta($post->ID, '_lead_company', true),
'Focus area' => get_post_meta($post->ID, '_lead_focus', true),
'Message' => get_post_meta($post->ID, '_lead_message', true),
];
}
echo '<div class="coaching-admin-meta">';
foreach ($fields as $label => $value) {
echo '<p><strong>' . esc_html($label) . ':</strong><br>' . nl2br(esc_html((string) $value)) . '</p>';
}
echo '</div>';
}
function coaching_mvp_testimonial_meta_box_html($post) {
wp_nonce_field('coaching_testimonial_meta', 'coaching_testimonial_meta_nonce');
$role = get_post_meta($post->ID, '_testimonial_role', true);
echo '<p><label for="coaching-testimonial-role"><strong>Role / context</strong></label></p>';
echo '<input type="text" id="coaching-testimonial-role" name="coaching_testimonial_role" value="' . esc_attr((string) $role) . '" style="width:100%;" />';
echo '<p class="description">Example: Founder, Sample Client</p>';
}
function coaching_mvp_save_testimonial_meta($post_id) {
if (!isset($_POST['coaching_testimonial_meta_nonce']) || !wp_verify_nonce(wp_unslash($_POST['coaching_testimonial_meta_nonce']), 'coaching_testimonial_meta')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (isset($_POST['coaching_testimonial_role'])) {
update_post_meta($post_id, '_testimonial_role', sanitize_text_field(wp_unslash($_POST['coaching_testimonial_role'])));
}
}
add_action('save_post_testimonial', 'coaching_mvp_save_testimonial_meta');
function coaching_mvp_current_request_origin() {
if (defined('WP_CLI') && WP_CLI) {
return null;
}
$host = '';
if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$parts = explode(',', (string) $_SERVER['HTTP_X_FORWARDED_HOST']);
$host = trim(end($parts));
} elseif (!empty($_SERVER['HTTP_HOST'])) {
$host = trim((string) $_SERVER['HTTP_HOST']);
}
if ($host === '' || preg_match('/[^a-z0-9\-\.:\[\]]/i', $host)) {
return null;
}
$scheme = 'http';
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
$parts = explode(',', (string) $_SERVER['HTTP_X_FORWARDED_PROTO']);
$candidate = strtolower(trim(end($parts)));
if (in_array($candidate, ['http', 'https'], true)) {
$scheme = $candidate;
}
} elseif (!empty($_SERVER['REQUEST_SCHEME']) && in_array($_SERVER['REQUEST_SCHEME'], ['http', 'https'], true)) {
$scheme = $_SERVER['REQUEST_SCHEME'];
} elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
$scheme = 'https';
}
return $scheme . '://' . $host;
}
function coaching_mvp_should_replace_local_host($url) {
$host = wp_parse_url($url, PHP_URL_HOST);
return in_array($host, ['localhost', '127.0.0.1', '::1'], true);
}
function coaching_mvp_replace_local_origin($url) {
$origin = coaching_mvp_current_request_origin();
if (!$origin || !coaching_mvp_should_replace_local_host($url)) {
return $url;
}
$path = (string) wp_parse_url($url, PHP_URL_PATH);
$query = wp_parse_url($url, PHP_URL_QUERY);
$fragment = wp_parse_url($url, PHP_URL_FRAGMENT);
$rebuilt = rtrim($origin, '/') . $path;
if ($query) {
$rebuilt .= '?' . $query;
}
if ($fragment) {
$rebuilt .= '#' . $fragment;
}
return $rebuilt;
}
function coaching_mvp_filter_option_home($value) {
return coaching_mvp_replace_local_origin((string) $value);
}
add_filter('option_home', 'coaching_mvp_filter_option_home');
add_filter('option_siteurl', 'coaching_mvp_filter_option_home');
function coaching_mvp_filter_generated_url($url) {
return coaching_mvp_replace_local_origin((string) $url);
}
add_filter('home_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('site_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('content_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('plugins_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('includes_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('rest_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('network_home_url', 'coaching_mvp_filter_generated_url', 10, 1);
add_filter('network_site_url', 'coaching_mvp_filter_generated_url', 10, 1);
function coaching_mvp_replace_local_origin_in_html($html) {
$origin = coaching_mvp_current_request_origin();
if (!$origin || !is_string($html) || $html == '') {
return $html;
}
return str_replace(
['http://localhost', 'https://localhost', 'http://127.0.0.1', 'https://127.0.0.1'],
$origin,
$html
);
}
function coaching_mvp_filter_rendered_block_html($block_content) {
if (is_admin()) {
return $block_content;
}
return coaching_mvp_replace_local_origin_in_html($block_content);
}
add_filter('render_block', 'coaching_mvp_filter_rendered_block_html', 10, 1);