prod migration fixes: GTM removed, timer bar redesign, coach page jQuery fix, security .htaccess, async mail, archive-coach after footer

This commit is contained in:
2026-05-13 10:17:24 +03:00
parent 04a184f026
commit 7d5202d23a
8 changed files with 230 additions and 70 deletions

View File

@@ -1,3 +1,32 @@
# BEGIN Security
# Block .git directory
RedirectMatch 404 /\.git
# Block debug.log
<Files "debug.log">
Order allow,deny
Deny from all
</Files>
# Block xmlrpc.php
<Files "xmlrpc.php">
Order allow,deny
Deny from all
</Files>
# Block wp-config.php
<Files "wp-config.php">
Order allow,deny
Deny from all
</Files>
# Block .env files
<FilesMatch "^\.env">
Order allow,deny
Deny from all
</FilesMatch>
# END Security
# BEGIN WP Rocket v3.13.3
# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset UTF-8

View File

@@ -0,0 +1,33 @@
<?php
/**
* Purge nginx FastCGI cache on content changes.
* Clears entire cache when posts are published/updated/deleted
* or when comments are approved.
*/
defined('ABSPATH') || exit;
function pwh_purge_fastcgi_cache() {
$cache_dir = '/var/cache/nginx/fastcgi';
if ( ! is_dir( $cache_dir ) ) return;
// Shell-safe: rm contents of known directory
$cmd = 'rm -rf ' . escapeshellarg( $cache_dir ) . '/*';
@exec( $cmd );
}
// Post publish/update/delete/trash
add_action( 'transition_post_status', function( $new, $old, $post ) {
if ( $new === 'publish' || $old === 'publish' ) {
pwh_purge_fastcgi_cache();
}
}, 10, 3 );
// Comment approved
add_action( 'comment_post', 'pwh_purge_fastcgi_cache' );
add_action( 'edit_comment', 'pwh_purge_fastcgi_cache' );
// Menu/widget/theme changes
add_action( 'wp_update_nav_menu', 'pwh_purge_fastcgi_cache' );
add_action( 'update_option_sidebars_widgets', 'pwh_purge_fastcgi_cache' );
add_action( 'switch_theme', 'pwh_purge_fastcgi_cache' );

View File

@@ -633,21 +633,20 @@ if ( $coach_query->max_num_pages > 1 ): ?>
<?php echo do_shortcode('[contact-form-7 id="' . $idForm2 . '"]'); ?>
</section>
<script>
$(document).ready(function(){
$('form').addClass("pwh-form d-flex flex-column justify-content-between align-items-center");
$('form').attr("name","tariffs");
// Выпадающие списки в формах
PowerHouse.handleTariffsForm("form[name=tariffs]");
$('.coach-all-container').first().addClass('active');
$('.buttons-programm-wrap .button-programm').click(function() {
$('.coach-all-container').removeClass('active');
$('.buttons-programm-wrap .button-programm').removeClass('active');
$(this).addClass('active');
idButton = $(this).attr('data-id');
$('.coach-all-container-' + idButton).addClass('active');
});
});
</script>
<?php get_footer(); ?>
<script>
jQuery(function($){
$('.coach-all-container').first().addClass('active');
$('.buttons-programm-wrap .button-programm').click(function() {
$('.coach-all-container').removeClass('active');
$('.buttons-programm-wrap .button-programm').removeClass('active');
$(this).addClass('active');
var idButton = $(this).attr('data-id');
$('.coach-all-container-' + idButton).addClass('active');
});
$('form').addClass("pwh-form d-flex flex-column justify-content-between align-items-center");
$('form').attr("name","tariffs");
try { PowerHouse.handleTariffsForm("form[name=tariffs]"); } catch(e) {}
});
</script>

View File

@@ -148,7 +148,7 @@
$clubID = get_current_blog_id();
?>
<label onclick="AfterClub()">
<input type="radio" name="input-club" value="Родонитовая, 29" <?php echo ($clubID == 4) ? 'checked' : ''; ?>>
<input type="radio" name="input-club" value="Родонитовая, 29" <?php echo ($clubID == 4 || $clubID == 1) ? 'checked' : ''; ?>>
<span class="wpcf7-list-item-label">Родонитовая, 29 (с бассейном)</span>
</label>
<label onclick="AfterClub()">
@@ -168,7 +168,7 @@
<span class="wpcf7-list-item-label">Титова, 35а (с бассейном)</span>
</label>
<label onclick="AfterClub()">
<input type="radio" name="input-club" value="Татищева, 105">
<input type="radio" name="input-club" value="Татищева, 105" <?php echo ($clubID == 8) ? 'checked' : ''; ?>>
<span class="wpcf7-list-item-label">Татищева, 105 (с бассейном)</span>
</label>
</div>
@@ -275,6 +275,8 @@
</footer>
<!-- /.footer -->
<?php get_template_part('template-parts/timer'); ?>
<script type='application/ld+json'>
{

View File

@@ -4,6 +4,16 @@
@ini_set( 'post_max_size', '128M');
@ini_set( 'max_execution_time', '300' );
/* Dev: X-Robots-Tag noindex + robots.txt Disallow */
if ( defined('DOMAIN_CURRENT_SITE') && str_contains(DOMAIN_CURRENT_SITE, 'dev.') ) {
add_action('send_headers', function() {
header('X-Robots-Tag: noindex, nofollow, noarchive', true);
});
add_filter('robots_txt', function() {
return "User-agent: *\nDisallow: /\n";
}, 999);
}
/* Подключение скриптов и стилей */
function pwh_add_scripts() {
// Подключаем свежую версию jquery
@@ -324,13 +334,19 @@ function pwh_disable_cf7_schema_preload() {
}
add_action( 'wp_enqueue_scripts', 'pwh_disable_cf7_schema_preload', 20 );
/* Preload Stolzl fonts чтобы убрать цепочку usluga.css → stolzl woff2 */
/* Preload Stolzl fonts + inline @font-face чтобы шрифты применялись сразу без CLS */
function pwh_preload_stolzl_fonts() {
if ( ! is_page_template( 'page-main-new.php' ) && ! is_page_template( 'page-usluga.php' ) ) return;
$base = get_template_directory_uri() . '/dist/fonts/stolz/';
echo '<link rel="preload" href="' . $base . 'stolzl_book-webfont.woff2" as="font" type="font/woff2" crossorigin>' . "\n";
echo '<link rel="preload" href="' . $base . 'stolzl_light-webfont.woff2" as="font" type="font/woff2" crossorigin>' . "\n";
echo '<link rel="preload" href="' . $base . 'stolzl_regular-webfont.woff2" as="font" type="font/woff2" crossorigin>' . "\n";
// Inline @font-face — шрифты применяются сразу (preload + font-face в head = без CLS)
echo '<style>' . "\n";
echo '@font-face{font-family:stolzlbook;src:url(' . $base . 'stolzl_book-webfont.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}' . "\n";
echo '@font-face{font-family:stolzllight;src:url(' . $base . 'stolzl_light-webfont.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}' . "\n";
echo '@font-face{font-family:stolzlregular;src:url(' . $base . 'stolzl_regular-webfont.woff2) format("woff2");font-weight:400;font-style:normal;font-display:swap}' . "\n";
echo '</style>' . "\n";
}
add_action( 'wp_head', 'pwh_preload_stolzl_fonts', 2 );
@@ -353,8 +369,11 @@ function pwh_cls_fix_styles() {
if ( is_admin() ) return;
echo '<style>
.main__girl-img { width:187px; height:197px; aspect-ratio:187/197; }
.main-screen { position:relative; overflow:hidden; }
.main-screen { position:relative; overflow:hidden; min-height: 600px; }
@media (max-width:1000px) { .main-screen { min-height: 500px; } }
@media (max-width:450px) { .main-screen { min-height: 400px; } }
.main-screen__title { min-height: 4.5em; line-height: 1.1; position:relative; z-index:1; }
.main-screen__top { contain: layout style; }
.main-screen__top { position:relative; z-index:1; }
.cookie { contain:layout; }
.locations__map img { width:100%; height:auto; aspect-ratio:686/553; }
@@ -448,6 +467,81 @@ function pwh_cls_fix_styles() {
transform: scale(0.97);
opacity: 0.85;
}
/* Timer bar redesign */
@keyframes pwh-pulse { 0%,100%{transform:scale(1);opacity:1} 50%{transform:scale(1.12);opacity:.75} }
.timercontainer {
position: fixed !important;
left: 0; bottom: 0; width: 100%;
height: auto !important;
background: #fff !important;
z-index: 9990;
padding: 16px 0;
box-shadow: 0 -2px 16px rgba(0,0,0,.1);
}
.timercontainer .container { max-width: 960px; position: relative; }
.timercontainer .row {
align-items: center;
justify-content: center;
gap: 0;
}
.timer-left-text {
color: #333 !important;
font-size: 16px !important;
font-weight: 600;
line-height: 1.3;
text-align: right;
}
.timer-cards-number { text-align: center; }
.timer-cards-number span {
display: inline-block;
font-size: 3em !important;
font-weight: 800;
color: #333;
line-height: 1;
animation: pwh-pulse 2s ease-in-out infinite;
}
.timer-btn-wrap { text-align: left; }
.timer-btn-wrap a { text-decoration: none !important; }
.timer-btn {
background: linear-gradient(135deg, #e8834a 0%, #c94468 50%, #9b3a6a 100%) !important;
color: #fff !important;
padding: 14px 36px !important;
border: none !important;
border-radius: 50px;
font-size: 16px;
font-style: italic;
font-weight: 500;
cursor: pointer;
transition: opacity .2s, transform .15s;
white-space: nowrap;
}
.timer-btn:hover { opacity: .9; transform: translateY(-1px); }
/* Крестик закрытия */
.timercontainer .timer-close {
position: absolute;
top: -8px; right: 8px;
width: 28px; height: 28px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 50%;
font-size: 16px; line-height: 26px;
text-align: center;
color: #999;
cursor: pointer;
z-index: 2;
transition: background .15s, color .15s;
}
.timercontainer .timer-close:hover { background: #eee; color: #333; }
body { padding-bottom: 80px; }
@media (max-width: 575px) {
.timercontainer { padding: 10px 0; }
.timer-left-text { font-size: 13px !important; text-align: center; }
.timer-cards-number span { font-size: 2.2em !important; }
.timer-btn { padding: 10px 20px !important; font-size: 13px; }
body { padding-bottom: 65px; }
}
</style>';
}
add_action( 'wp_head', 'pwh_cls_fix_styles', 5 );
@@ -541,6 +635,8 @@ function pwh_quiz_reset_js() {
}
add_action( 'wp_footer', 'pwh_quiz_reset_js', 101 );
/* GTM удалён — Konget dedup fix больше не нужен */
/* Клиентский профайлинг форм — замер от клика до ответа */
function pwh_form_profiling_js() {
return; // ОТКЛЮЧЕНО — панель профайлинга выключена
@@ -640,6 +736,38 @@ function pwh_form_profiling_js() {
}
add_action( 'wp_footer', 'pwh_form_profiling_js', 102 );
/* Синхронизация select.form-club-selector и radio → hidden input[name="club"] (vanilla JS) */
function pwh_sync_club_field_js() {
?>
<script>
(function(){
// select dropdown → hidden club field
document.querySelectorAll('select.form-club-selector').forEach(function(sel){
var form = sel.closest('form');
if (!form) return;
var club = form.querySelector('input[name="club"]');
if (club && !club.value) club.value = sel.value;
sel.addEventListener('change', function(){
if (club) club.value = sel.value;
});
});
// radio[name="radio-club"] → hidden club field (квиз)
document.querySelectorAll('input[name="radio-club"]').forEach(function(radio){
radio.addEventListener('change', function(){
var form = this.closest('form');
if (!form) return;
var label = this.closest('.radio-item');
var text = label ? label.querySelector('label').textContent.trim() : '';
var club = form.querySelector('input[name="club"]');
if (club && text) club.value = text;
});
});
})();
</script>
<?php
}
add_action( 'wp_footer', 'pwh_sync_club_field_js', 103 );
/* Ленивая загрузка Yandex SmartCaptcha:
1) SDK грузится при первом взаимодействии (scroll/click/touch)
2) smartCaptcha.render() перехвачен — рендерит только когда контейнер в viewport
@@ -752,6 +880,8 @@ function pwh_defer_noncritical_js( $tag, $handle ) {
'wpfront-scroll-top',
'owl.carousel',
'matchHeight',
'swv', // CF7 validation JS
'contact-form-7', // CF7 основной JS
'cf7msm-js',
'jvcf7_jquery_validate', // + нормальный defer атрибут (плагин ставит через URL-хак)
'jvcf7_validation', // + нормальный defer атрибут
@@ -771,22 +901,7 @@ function pwh_defer_noncritical_js( $tag, $handle ) {
}
add_filter( 'script_loader_tag', 'pwh_defer_noncritical_js', 10, 2 );
if ( ! function_exists( 'add_defer_to_cf7' ) )
{
function add_defer_to_cf7( $url )
{
if ( // comment the following line out add 'defer' to all scripts
FALSE === strpos( $url, 'contact-form-7' ) or
FALSE === strpos( $url, '.js' )
)
{ // not our file
return $url;
}
// Must be a ', not "!
return "$url' defer='defer";
}
add_filter( 'clean_url', 'add_defer_to_cf7', 11, 1 );
}
/* Старый clean_url хак для CF7 defer удалён — CF7 defer'ится через pwh_defer_noncritical_js */
/* Хлебные крошки */
require_once(TEMPLATEPATH . '/inc/breadcrambs.php');
@@ -1407,7 +1522,7 @@ if ( function_exists('wpcf7_add_form_tag') ) { wpcf7_add_form_tag('current_club'
function select_list_clubs_cf7_func() {
$clubs = [];
$list_clubs = '<select class="form-club-selector">';
$list_clubs = '<select class="form-club-selector" name="club-selector">';
$default_club_id = 0;
// получить список всех клубов из базы
$sites = get_sites(array(
@@ -1851,7 +1966,19 @@ function add_query_vars_filter( $vars ){
add_action( 'wpcf7_before_send_mail', 'wp_kama_wpcf7_before_send_mail_action' );
function wp_kama_wpcf7_before_send_mail_action( $contact_form ){
$post_data = WPCF7_Submission::get_instance()->get_posted_data();
$club = json_encode($post_data["club"][0] ?? $post_data["club"] ?? '');
$club_val = $post_data["club"] ?? '';
$club_raw = is_array( $club_val ) ? ( $club_val[0] ?? '' ) : $club_val;
// Если клуб пустой — берём из select dropdown, сессии или имени подсайта
if ( empty( $club_raw ) && ! empty( $_POST['club-selector'] ) ) {
$club_raw = sanitize_text_field( $_POST['club-selector'] );
}
if ( empty( $club_raw ) ) {
$club_raw = $_SESSION['club']['name'] ?? '';
}
if ( empty( $club_raw ) && get_current_blog_id() > 1 ) {
$club_raw = get_bloginfo( 'name' );
}
$club = json_encode( $club_raw );
$name = json_encode($post_data["customerName"] ?? '');
$phone = json_encode($post_data["customerPhone"] ?? '');
$adress = json_encode(WPCF7_Submission::get_instance()->get_posted_data('url-address') ?? '');

View File

@@ -72,24 +72,9 @@ if (have_rows('club_slides')) {
<?php wp_head(); ?>
<!-- Google Tag Manager — загрузка только по взаимодействию -->
<script>window.dataLayer=window.dataLayer||[];
(function(){var loaded=false;function loadGTM(){if(loaded)return;loaded=true;
dataLayer.push({'gtm.start':new Date().getTime(),event:'gtm.js'});
var f=document.getElementsByTagName('script')[0],j=document.createElement('script');
j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id=GTM-N97R8J5';
f.parentNode.insertBefore(j,f);}
['scroll','click','touchstart','mousemove','keydown'].forEach(function(e){
document.addEventListener(e,loadGTM,{once:true,passive:true});});})();</script>
<!-- End Google Tag Manager -->
</head>
<body <?php body_class(); ?>>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N97R8J5"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) --></div>
<header class="header-home header-main-text-adj<?php if (get_current_blog_id() != 1) echo ' header-club large-menu'; ?>">
<div class="top-nav">

View File

@@ -89,26 +89,10 @@ endif; ?>
<?php wp_head(); ?>
<!-- Google Tag Manager — отложенная загрузка -->
<script>window.dataLayer=window.dataLayer||[];
(function(){var loaded=false;function loadGTM(){if(loaded)return;loaded=true;
dataLayer.push({'gtm.start':new Date().getTime(),event:'gtm.js'});
var f=document.getElementsByTagName('script')[0],j=document.createElement('script');
j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id=GTM-N97R8J5';
f.parentNode.insertBefore(j,f);}
['scroll','click','touchstart','mousemove'].forEach(function(e){
document.addEventListener(e,loadGTM,{once:true,passive:true});});})();</script>
<!-- End Google Tag Manager -->
</head>
<body <?php body_class(); ?>>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N97R8J5"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<header class="header large-menu">
<div class="container-fluid">
<div class="top-nav">

View File

@@ -28,6 +28,7 @@ if ($showTimer):
?>
<div class="timercontainer">
<section class="container ">
<span class="timer-close" onclick="this.closest('.timercontainer').style.display='none';document.body.style.paddingBottom='0';">&times;</span>
<div class="row">
<div class="col-5 col-sm-5 col-md-4 timer-left-text">