Global-2026-07-15

This commit is contained in:
Dekart Deploy Bot 2026-07-15 14:09:27 +00:00
parent 15ac1f81aa
commit 3d9218df11
5 changed files with 60 additions and 96 deletions

View File

@ -643,6 +643,14 @@ function add_carbon() {
Field::make( 'textarea', 'teacher_about', 'О педагоге (на этой странице)' )
->set_width( 100 )
->set_help_text( 'Краткое описание для этой страницы. Если оставить пустым — используется значение из карточки преподавателя.' ),
Field::make( 'text', 'teacher_badge', 'Бейдж (на этой странице)' )
->set_width( 50 )
->set_default_value( '👶 Работает с дошкольниками' )
->set_help_text( 'Если оставить пустым — скрывается.' ),
Field::make( 'text', 'teacher_exp', 'Опыт (на этой странице)' )
->set_width( 50 )
->set_default_value( '39 лет' )
->set_help_text( 'Только число: «39» или строка: «39 лет». На странице выведется как 📅 Стаж: X. Если пусто — рассчитывается из карточки преподавателя.' ),
)),
))
// ====================================================
@ -668,6 +676,10 @@ function add_carbon() {
Field::make( 'text', 'pksh_prog_base_price_single', 'Стоимость разового занятия' )
->set_width( 50 )
->set_default_value( '1 000 ₽' ),
Field::make( 'text', 'pksh_prog_base_price_razov', 'Стоимость разового занятия ВНЕ абонемента' )
->set_width( 50 )
->set_default_value( '1 200 ₽' )
->set_help_text( 'Отдельная цена для «Разовое занятие вне абонемента: …». Если пусто — используется price_single.' ),
Field::make( 'text', 'pksh_prog_base_urgency', 'Срочность (мест в группе)' )
->set_width( 100 )
->set_default_value( 'Осталось 2 места в группе' ),
@ -688,6 +700,10 @@ function add_carbon() {
Field::make( 'text', 'pksh_prog_prem_price_single', 'Стоимость разового занятия' )
->set_width( 50 )
->set_default_value( '1 500 ₽' ),
Field::make( 'text', 'pksh_prog_prem_price_razov', 'Стоимость разового занятия ВНЕ абонемента' )
->set_width( 50 )
->set_default_value( '2 000 ₽' )
->set_help_text( 'Отдельная цена для «Разовое занятие вне абонемента: …». Если пусто — используется price_single.' ),
Field::make( 'text', 'pksh_prog_prem_urgency', 'Срочность (мест в группе)' )
->set_width( 100 )
->set_default_value( 'Осталось 3 места в группе' ),

View File

@ -320,36 +320,38 @@ wp_cache_set( $cache_key, $this->branch['social'], 'dekart_branch', DAY_IN_SECON
/**
* Данные базовой программы
* @return array{name: string, subname: string, schedule: string, price_sub: string, price_single: string, urgency: string}
* @return array{name: string, subname: string, schedule: string, price_sub: string, price_single: string, price_razov: string, urgency: string}
*/
public function get_base_program(): array {
if ( ! array_key_exists( 'base', $this->programs ) ) {
$this->programs['base'] = array(
'name' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_name' ) ?: 'Уверенный старт',
'subname' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_subname' ) ?: '2 раза в неделю — комфортный темп без перегрузки',
'schedule' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_schedule' ) ?: 'вт, чт — 18:0019:30',
'price_sub' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_price_sub' ) ?: '7 500 ₽',
'price_single' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_price_single' ) ?: '1 000 ₽',
'urgency' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_urgency' ) ?: 'Осталось 2 места в группе',
);
$this->programs['base'] = array(
'name' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_name' ) ?: 'Уверенный старт',
'subname' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_subname' ) ?: '2 раза в неделю — комфортный темп без перегрузки',
'schedule' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_schedule' ) ?: 'вт, чт — 18:0019:30',
'price_sub' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_price_sub' ) ?: '7 500 ₽',
'price_single' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_price_single' ) ?: '1 000 ₽',
'price_razov' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_price_razov' ) ?: '',
'urgency' => carbon_get_post_meta( $this->post_id, 'pksh_prog_base_urgency' ) ?: 'Осталось 2 места в группе',
);
}
return $this->programs['base'];
}
/**
* Данные премиум-программы
* @return array{name: string, subname: string, schedule: string, price_sub: string, price_single: string, urgency: string}
* @return array{name: string, subname: string, schedule: string, price_sub: string, price_single: string, price_razov: string, urgency: string}
*/
public function get_premium_program(): array {
if ( ! array_key_exists( 'prem', $this->programs ) ) {
$this->programs['prem'] = array(
'name' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_name' ) ?: 'Результат за 3 месяца',
'subname' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_subname' ) ?: '3 раза в неделю — быстрый прогресс',
'schedule' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_schedule' ) ?: 'пн, ср, пт — 16:3018:00',
'price_sub' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_price_sub' ) ?: '10 500 ₽',
'price_single' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_price_single' ) ?: '1 500 ₽',
'urgency' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_urgency' ) ?: 'Осталось 3 места в группе',
);
$this->programs['prem'] = array(
'name' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_name' ) ?: 'Результат за 3 месяца',
'subname' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_subname' ) ?: '3 раза в неделю — быстрый прогресс',
'schedule' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_schedule' ) ?: 'пн, ср, пт — 16:3018:00',
'price_sub' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_price_sub' ) ?: '10 500 ₽',
'price_single' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_price_single' ) ?: '1 500 ₽',
'price_razov' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_price_razov' ) ?: '',
'urgency' => carbon_get_post_meta( $this->post_id, 'pksh_prog_prem_urgency' ) ?: 'Осталось 3 места в группе',
);
}
return $this->programs['prem'];
}

View File

@ -155,13 +155,7 @@ function dekart_schema_output(): void {
$graph[] = $faq;
}
// 11b. QAPage — ключевые вопросы для AI citation readiness
$qa = dekart_schema_qapage();
if ( $qa ) {
$graph[] = $qa;
}
// 11c. Event — бесплатное пробное занятие
// 11b. Event — бесплатное пробное занятие
$event = dekart_schema_trial_event();
if ( $event ) {
$graph[] = $event;
@ -1415,57 +1409,6 @@ function dekart_schema_trial_event(): ?array {
);
}
/**
* QAPage ключевые вопросы для AI citation readiness.
* Google retired FAQ rich results May 2026, но QAPage важен для AI Overviews/ChatGPT/Perplexity.
*
* @see https://schema.org/QAPage
*/
function dekart_schema_qapage(): ?array {
if ( ! is_page( 2 ) ) {
return null;
}
$page_url = dekart_schema_page_url();
$faq_items = carbon_get_post_meta( get_the_ID(), 'pksh_faq_items' );
if ( empty( $faq_items ) || ! is_array( $faq_items ) ) {
return null;
}
// Берём только 3-5 ключевых вопросов (самые частые)
$key_questions = array_slice( $faq_items, 0, 5 );
$main_entity = array();
foreach ( $key_questions as $item ) {
$question = isset( $item['faq_question'] ) ? trim( $item['faq_question'] ) : '';
$answer = isset( $item['faq_answer'] ) ? trim( $item['faq_answer'] ) : '';
if ( empty( $question ) || empty( $answer ) ) {
continue;
}
$main_entity[] = array(
'@type' => 'Question',
'name' => wp_strip_all_tags( $question ),
'acceptedAnswer' => array(
'@type' => 'Answer',
'text' => wp_strip_all_tags( $answer ),
),
);
}
if ( empty( $main_entity ) ) {
return null;
}
return array(
'@type' => 'QAPage',
'@id' => $page_url . '#qapage',
'mainEntity' => $main_entity,
);
}
/**
* Offer / AggregateOffer с UnitPriceSpecification.
* Добавляет priceSpecification с unitCode: 'MON' для цен за месяц.

View File

@ -45,7 +45,7 @@ $prem = $data->get_premium_program();
<div class="prog-card__pricing">
<div class="prog-card__price prog-card__price--premium"><?php echo esc_html( $prem['price_sub'] ); ?> <span class="prog-card__price-period">стоимость абонемента за 4 недели</span></div>
<div class="prog-card__price-sub"><?php echo esc_html( $prem['price_single'] ); ?> за занятие — дешевле репетитора</div>
<div class="prog-card__price-single">Разовое занятие вне абонемента: <?php echo esc_html( $prem['price_single'] ); ?></div>
<div class="prog-card__price-single">Разовое занятие вне абонемента: <?php echo esc_html( $prem['price_razov'] ?: $prem['price_single'] ); ?></div>
<div class="prog-card__urgency"><?php echo esc_html( $prem['urgency'] ); ?></div>
</div>
@ -124,7 +124,7 @@ $prem = $data->get_premium_program();
<div class="prog-card__pricing">
<div class="prog-card__price"><?php echo esc_html( $base['price_sub'] ); ?> <span class="prog-card__price-period">стоимость абонемента за 4 недели</span></div>
<div class="prog-card__price-sub"><?php echo esc_html( $base['price_single'] ); ?> за занятие — дешевле репетитора</div>
<div class="prog-card__price-single">Разовое занятие вне абонемента: <?php echo esc_html( $base['price_single'] ); ?></div>
<div class="prog-card__price-single">Разовое занятие вне абонемента: <?php echo esc_html( $base['price_razov'] ?: $base['price_single'] ); ?></div>
<div class="prog-card__urgency"><?php echo esc_html( $base['urgency'] ); ?></div>
</div>

View File

@ -32,6 +32,8 @@ $teachers = $data->get_teachers();
$t_id = $item['teacher_id'] ?? 0;
$t_subj = $item['teacher_subject'] ?? '';
$t_about = $item['teacher_about'] ?? '';
$t_badge = $item['teacher_badge'] ?? '';
$t_exp = $item['teacher_exp'] ?? '';
$t_post = $t_id ? get_post( $t_id ) : null;
$t_name = $t_post ? $t_post->post_title : '—';
@ -51,6 +53,18 @@ $teachers = $data->get_teachers();
if ( empty( $t_about ) && $t_post ) {
$t_about = get_post_meta( $t_id, '_teacher_about', true );
}
if ( empty( $t_exp ) && $t_post ) {
$start_year = get_post_meta( $t_id, '_teacher_start_year', true );
if ( $start_year && is_numeric( $start_year ) ) {
$e = (int) date( 'Y' ) - (int) $start_year;
if ( $e > 0 ) {
$t_exp = $e . ' лет';
}
}
} elseif ( ! empty( $t_exp ) && ctype_digit( trim( $t_exp ) ) ) {
$t_exp = trim( $t_exp ) . ' лет';
}
?>
<div class="pksh-teachers__item">
<div class="pksh-teachers__card">
@ -71,26 +85,15 @@ $teachers = $data->get_teachers();
<?php if ( $t_subj ) : ?>
<p class="pksh-teachers__subj"><?php echo esc_html( $t_subj ); ?></p>
<?php endif; ?>
<?php if ( $t_post ) :
$t_desc = get_post_meta( $t_id, '_teacher_description', true );
if ( ! empty( $t_desc ) ) : ?>
<p class="pksh-teachers__desc"><?php echo esc_html( wp_strip_all_tags( $t_desc ) ); ?></p>
<?php endif; ?>
<?php if ( $t_about ) : ?>
<p class="pksh-teachers__desc"><?php echo esc_html( wp_strip_all_tags( $t_about ) ); ?></p>
<?php endif; ?>
<div class="pksh-teachers__meta">
<span class="pksh-teachers__meta-badge">👶 Работает с дошкольниками</span>
<?php if ( $t_post ) :
$exp_years = '';
$start_year = get_post_meta( $t_id, '_teacher_start_year', true );
if ( $start_year && is_numeric( $start_year ) ) {
$exp = (int) date( 'Y' ) - (int) $start_year;
if ( $exp > 0 ) {
$exp_years = $exp . ' лет';
}
}
if ( $exp_years ) : ?>
<span class="pksh-teachers__meta-exp">📅 Стаж: <?php echo esc_html( $exp_years ); ?></span>
<?php endif; ?>
<?php if ( $t_badge ) : ?>
<span class="pksh-teachers__meta-badge"><?php echo esc_html( $t_badge ); ?></span>
<?php endif; ?>
<?php if ( $t_exp ) : ?>
<span class="pksh-teachers__meta-exp">📅 Стаж: <?php echo esc_html( $t_exp ); ?></span>
<?php endif; ?>
</div>
<button class="pksh-teachers__btn open-bitrix-form">Записаться к этому педагогу</button>