526 lines
19 KiB
PHP
526 lines
19 KiB
PHP
<?php
|
||
/**
|
||
* Pksh_Data — централизованная загрузка данных для page-podgotovka-k-shkole.php
|
||
*
|
||
* Синглтон. Кэширует все carbon_get_post_meta() и get_option() вызовы.
|
||
* Каждый template-part вызывает Pksh_Data::instance() -> get_*().
|
||
* Повторные вызовы instance() возвращают тот же объект — без дублирования запросов.
|
||
*
|
||
* @package Dekart
|
||
*/
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
class Pksh_Data {
|
||
|
||
private static ?Pksh_Data $instance = null;
|
||
private int $post_id;
|
||
|
||
/** @var array Кэш branch-данных (get_option с fallback) */
|
||
private array $branch = [];
|
||
|
||
/** @var array Кэш page-specific meta */
|
||
private array $page = [];
|
||
|
||
/** @var array|null Кэш complex полей */
|
||
private ?array $social = null;
|
||
private array $programs = [];
|
||
private ?array $compare = null;
|
||
private ?array $teachers = null;
|
||
private ?array $reviews = null;
|
||
private ?array $faq = null;
|
||
private ?array $gallery = null;
|
||
|
||
private function __construct() {
|
||
$this->post_id = get_the_ID();
|
||
}
|
||
|
||
/**
|
||
* Получить экземпляр (синглтон)
|
||
*/
|
||
public static function instance(): self {
|
||
if ( null === self::$instance ) {
|
||
self::$instance = new self();
|
||
}
|
||
return self::$instance;
|
||
}
|
||
|
||
// ============================================================
|
||
// BRANCH / OPTION DATA (get_option -> theme_option -> post_meta)
|
||
// ============================================================
|
||
|
||
public function get_address(): string {
|
||
$cache_key = 'dekart_branch_address';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'address', $this->branch ) ) {
|
||
$this->branch['address'] = get_option( 'branch_address' ) ?:
|
||
carbon_get_theme_option( 'site_address' ) ?:
|
||
carbon_get_post_meta( $this->post_id, 'contact_address' ) ?:
|
||
'';
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['address'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['address'];
|
||
}
|
||
|
||
public function get_coords(): string {
|
||
$cache_key = 'dekart_branch_coords';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'coords', $this->branch ) ) {
|
||
$this->branch['coords'] = get_option( 'branch_coords' ) ?:
|
||
carbon_get_post_meta( $this->post_id, 'contact_location' ) ?:
|
||
'';
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['coords'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['coords'];
|
||
}
|
||
|
||
public function get_phone(): string {
|
||
$cache_key = 'dekart_branch_phone';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'phone', $this->branch ) ) {
|
||
$this->branch['phone'] = get_option( 'branch_phone' ) ?:
|
||
carbon_get_theme_option( 'site_phone' ) ?:
|
||
carbon_get_post_meta( $this->post_id, 'contact_tel' ) ?:
|
||
'';
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['phone'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['phone'];
|
||
}
|
||
|
||
public function get_phone_clean(): string {
|
||
if ( ! array_key_exists( 'phone_clean', $this->branch ) ) {
|
||
$this->branch['phone_clean'] = preg_replace( '/[^0-9+]/', '', $this->get_phone() );
|
||
}
|
||
return $this->branch['phone_clean'];
|
||
}
|
||
|
||
public function get_email(): string {
|
||
$cache_key = 'dekart_branch_email';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'email', $this->branch ) ) {
|
||
$this->branch['email'] = get_option( 'branch_email' ) ?:
|
||
carbon_get_theme_option( 'site_mail' ) ?:
|
||
carbon_get_post_meta( $this->post_id, 'contact_mail' ) ?:
|
||
'';
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['email'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['email'];
|
||
}
|
||
|
||
public function get_name(): string {
|
||
$cache_key = 'dekart_branch_name';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'name', $this->branch ) ) {
|
||
$this->branch['name'] = get_option( 'branch_name' ) ?:
|
||
carbon_get_theme_option( 'site_name' ) ?:
|
||
'Декарт';
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['name'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['name'];
|
||
}
|
||
|
||
public function get_city_prep(): string {
|
||
$cache_key = 'dekart_branch_city_prep';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'city_prep', $this->branch ) ) {
|
||
$this->branch['city_prep'] = get_option( 'branch_city_prep', 'в Щёлково' );
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['city_prep'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['city_prep'];
|
||
}
|
||
|
||
public function get_city_genitive(): string {
|
||
$genitive = get_option( 'branch_city_genitive', '' );
|
||
if ( ! empty( $genitive ) ) {
|
||
return $genitive;
|
||
}
|
||
$clean = $this->get_city_clean();
|
||
if ( str_ends_with( $clean, 'ово' ) || str_ends_with( $clean, 'ево' ) || str_ends_with( $clean, 'ино' ) || str_ends_with( $clean, 'ыно' ) ) {
|
||
return mb_substr( $clean, 0, -1 ) . 'а';
|
||
}
|
||
return $clean;
|
||
}
|
||
|
||
public function get_city_clean(): string {
|
||
if ( ! array_key_exists( 'city_clean', $this->branch ) ) {
|
||
$this->branch['city_clean'] = str_replace( array( 'в ', 'В ' ), '', $this->get_city_prep() );
|
||
}
|
||
return $this->branch['city_clean'];
|
||
}
|
||
|
||
public function get_ext_review_count(): string {
|
||
$cache_key = 'dekart_branch_ext_review_count';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'ext_review_count', $this->branch ) ) {
|
||
$this->branch['ext_review_count'] = get_option( 'branch_ext_review_count', '247' );
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['ext_review_count'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['ext_review_count'];
|
||
}
|
||
|
||
public function get_social_links(): array {
|
||
$cache_key = 'dekart_branch_social';
|
||
$cached = wp_cache_get( $cache_key, 'dekart_branch' );
|
||
if ( false !== $cached ) {
|
||
return $cached;
|
||
}
|
||
if ( ! array_key_exists( 'social', $this->branch ) ) {
|
||
$raw = get_option( 'branch_social' ) ?:
|
||
carbon_get_post_meta( $this->post_id, 'social_media' ) ?:
|
||
[];
|
||
$this->branch['social'] = is_array( $raw ) ? $raw : [];
|
||
}
|
||
wp_cache_set( $cache_key, $this->branch['social'], 'dekart_branch', DAY_IN_SECONDS );
|
||
return $this->branch['social'];
|
||
}
|
||
|
||
public function get_logistics_walk(): string {
|
||
if ( ! array_key_exists( 'logistics_walk', $this->branch ) ) {
|
||
$this->branch['logistics_walk'] = get_option( 'branch_logistics_walk', '5 минут пешком от ТЦ «Глобус»' );
|
||
}
|
||
return $this->branch['logistics_walk'];
|
||
}
|
||
|
||
public function get_logistics_parking(): string {
|
||
if ( ! array_key_exists( 'logistics_parking', $this->branch ) ) {
|
||
$this->branch['logistics_parking'] = get_option( 'branch_logistics_parking', 'Есть бесплатная парковка у входа' );
|
||
}
|
||
return $this->branch['logistics_parking'];
|
||
}
|
||
|
||
public function get_logistics_nearby(): string {
|
||
if ( ! array_key_exists( 'logistics_nearby', $this->branch ) ) {
|
||
$this->branch['logistics_nearby'] = get_option( 'branch_logistics_schools', 'Рядом со школами №9 и №12, детским садом №15' );
|
||
}
|
||
return $this->branch['logistics_nearby'];
|
||
}
|
||
|
||
// ============================================================
|
||
// AUTHOR / DATES (E-E-A-T / GEO)
|
||
// ============================================================
|
||
|
||
public function get_author_name(): string {
|
||
if ( ! array_key_exists( 'author_name', $this->page ) ) {
|
||
$this->page['author_name'] = carbon_get_post_meta( $this->post_id, 'pksh_author_name' )
|
||
?: get_option( 'branch_og_site_name' )
|
||
?: get_option( 'branch_name' )
|
||
?: carbon_get_theme_option( 'site_name' )
|
||
?: 'Детский центр «Декарт»';
|
||
}
|
||
return $this->page['author_name'];
|
||
}
|
||
|
||
/**
|
||
* Количество лет на рынке (из года основания).
|
||
* Автоматически: текущий год − год основания.
|
||
* Источник: CF schema_founded → Settings API branch_founded.
|
||
* Если год основания не задан — 0.
|
||
*/
|
||
public function get_years_on_market(): int {
|
||
if ( ! array_key_exists( 'years_market', $this->page ) ) {
|
||
$founded = carbon_get_theme_option( 'schema_founded' );
|
||
if ( empty( $founded ) ) {
|
||
$founded = get_option( 'branch_founded' );
|
||
}
|
||
if ( ! empty( $founded ) && is_string( $founded ) && is_numeric( $founded ) ) {
|
||
$this->page['years_market'] = (int) date( 'Y' ) - (int) $founded;
|
||
} else {
|
||
$this->page['years_market'] = 0;
|
||
}
|
||
}
|
||
return $this->page['years_market'];
|
||
}
|
||
|
||
public function get_page_publish_date(): string {
|
||
if ( ! array_key_exists( 'publish_date', $this->page ) ) {
|
||
$post = get_post( $this->post_id );
|
||
$this->page['publish_date'] = $post ? get_the_date( 'c', $post ) : '';
|
||
}
|
||
return $this->page['publish_date'];
|
||
}
|
||
|
||
public function get_page_modified_date(): string {
|
||
if ( ! array_key_exists( 'modified_date', $this->page ) ) {
|
||
$post = get_post( $this->post_id );
|
||
$this->page['modified_date'] = $post ? get_the_modified_date( 'c', $post ) : '';
|
||
}
|
||
return $this->page['modified_date'];
|
||
}
|
||
|
||
// ============================================================
|
||
// HERO / BANNER
|
||
// ============================================================
|
||
|
||
public function get_banner_image_id(): int {
|
||
if ( ! array_key_exists( 'banner_image_id', $this->page ) ) {
|
||
$this->page['banner_image_id'] = (int) carbon_get_post_meta( $this->post_id, 'banner_image' );
|
||
}
|
||
return $this->page['banner_image_id'];
|
||
}
|
||
|
||
public function get_h1(): string {
|
||
if ( ! array_key_exists( 'h1', $this->page ) ) {
|
||
$this->page['h1'] = carbon_get_post_meta( $this->post_id, 'banner_h1' ) ?: 'Подготовка к школе';
|
||
}
|
||
return $this->page['h1'];
|
||
}
|
||
|
||
public function get_subtitle(): string {
|
||
if ( ! array_key_exists( 'subtitle', $this->page ) ) {
|
||
$this->page['subtitle'] = carbon_get_post_meta( $this->post_id, 'banner_subtitle' ) ?:
|
||
'Первое занятие — бесплатно. Ребёнок научится читать, считать и писать в игровой форме. Группы до 10 человек.';
|
||
}
|
||
return $this->page['subtitle'];
|
||
}
|
||
|
||
public function get_subtitle_footnote_link(): string {
|
||
if ( ! array_key_exists( 'subtitle_footnote_link', $this->page ) ) {
|
||
$this->page['subtitle_footnote_link'] = carbon_get_post_meta( $this->post_id, 'banner_subtitle_footnote_link' ) ?: '';
|
||
}
|
||
return $this->page['subtitle_footnote_link'];
|
||
}
|
||
|
||
/**
|
||
* Определение для AI-цитирования (GEO, первые 60 слов).
|
||
* Заполняется в админке: вкладка "🖼️ Герой" -> поле "Определение для AI".
|
||
*/
|
||
public function get_hero_definition(): string {
|
||
if ( ! array_key_exists( 'hero_definition', $this->page ) ) {
|
||
$this->page['hero_definition'] = carbon_get_post_meta( $this->post_id, 'pksh_hero_definition' ) ?: '';
|
||
}
|
||
return $this->page['hero_definition'];
|
||
}
|
||
|
||
// ============================================================
|
||
// SOCIAL COUNTERS (complex)
|
||
// ============================================================
|
||
|
||
public function get_social_counters(): array {
|
||
if ( null === $this->social ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_social_counters' );
|
||
$this->social = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->social;
|
||
}
|
||
|
||
public static function social_icons(): array {
|
||
return array( 'icon-graduation', 'icon-calendar', 'icon-star-filled', 'icon-teacher' );
|
||
}
|
||
|
||
// ============================================================
|
||
// PROGRAMS
|
||
// ============================================================
|
||
|
||
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:00–19: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'];
|
||
}
|
||
|
||
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:30–18: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'];
|
||
}
|
||
|
||
// ============================================================
|
||
// GEO ANSWER BLOCKS (self-contained, 134-167 слов)
|
||
// ============================================================
|
||
|
||
public function get_geo_answer_programs(): string {
|
||
if ( ! array_key_exists( 'geo_answer_programs', $this->page ) ) {
|
||
$this->page['geo_answer_programs'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_answer_programs' ) ?: '';
|
||
}
|
||
return $this->page['geo_answer_programs'];
|
||
}
|
||
|
||
public function get_geo_answer_results(): string {
|
||
if ( ! array_key_exists( 'geo_answer_results', $this->page ) ) {
|
||
$this->page['geo_answer_results'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_answer_results' ) ?: '';
|
||
}
|
||
return $this->page['geo_answer_results'];
|
||
}
|
||
|
||
public function get_geo_answer_howitworks(): string {
|
||
if ( ! array_key_exists( 'geo_answer_howitworks', $this->page ) ) {
|
||
$this->page['geo_answer_howitworks'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_answer_howitworks' ) ?: '';
|
||
}
|
||
return $this->page['geo_answer_howitworks'];
|
||
}
|
||
|
||
public function get_geo_question_1(): string {
|
||
if ( ! array_key_exists( 'geo_q1', $this->page ) ) {
|
||
$this->page['geo_q1'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_q1' ) ?: '';
|
||
}
|
||
return $this->page['geo_q1'];
|
||
}
|
||
|
||
public function get_geo_question_2(): string {
|
||
if ( ! array_key_exists( 'geo_q2', $this->page ) ) {
|
||
$this->page['geo_q2'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_q2' ) ?: '';
|
||
}
|
||
return $this->page['geo_q2'];
|
||
}
|
||
|
||
public function get_geo_question_3(): string {
|
||
if ( ! array_key_exists( 'geo_q3', $this->page ) ) {
|
||
$this->page['geo_q3'] = carbon_get_post_meta( $this->post_id, 'pksh_geo_q3' ) ?: '';
|
||
}
|
||
return $this->page['geo_q3'];
|
||
}
|
||
|
||
// ============================================================
|
||
// COMPARE TABLE (complex)
|
||
// ============================================================
|
||
|
||
public function get_compare_rows(): array {
|
||
if ( null === $this->compare ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_compare_rows' );
|
||
$this->compare = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->compare;
|
||
}
|
||
|
||
public function get_compare_footnote(): string {
|
||
if ( ! array_key_exists( 'footnote', $this->page ) ) {
|
||
$this->page['footnote'] = carbon_get_post_meta( $this->post_id, 'pksh_compare_footnote' ) ?: '';
|
||
}
|
||
return $this->page['footnote'];
|
||
}
|
||
|
||
// ============================================================
|
||
// TEACHERS (complex)
|
||
// ============================================================
|
||
|
||
public function get_teachers(): array {
|
||
if ( null === $this->teachers ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_teachers' );
|
||
$this->teachers = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->teachers;
|
||
}
|
||
|
||
// ============================================================
|
||
// REVIEWS (complex)
|
||
// ============================================================
|
||
|
||
public function get_reviews(): array {
|
||
if ( null === $this->reviews ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_reviews_list' );
|
||
$this->reviews = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->reviews;
|
||
}
|
||
|
||
// ============================================================
|
||
// FAQ (complex)
|
||
// ============================================================
|
||
|
||
public function get_faq_items(): array {
|
||
if ( null === $this->faq ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_faq_items' );
|
||
$this->faq = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->faq;
|
||
}
|
||
|
||
// ============================================================
|
||
// GALLERY (complex)
|
||
// ============================================================
|
||
|
||
public function get_gallery(): array {
|
||
if ( null === $this->gallery ) {
|
||
$raw = carbon_get_post_meta( $this->post_id, 'pksh_gallery' );
|
||
$this->gallery = is_array( $raw ) ? $raw : [];
|
||
}
|
||
return $this->gallery;
|
||
}
|
||
|
||
// ============================================================
|
||
// HONEST TIMER
|
||
// ============================================================
|
||
|
||
public function get_honest_deadline(): int {
|
||
if ( ! array_key_exists( 'deadline', $this->page ) ) {
|
||
$this->page['deadline'] = function_exists( 'dekart_get_honest_deadline' )
|
||
? (int) dekart_get_honest_deadline()
|
||
: 0;
|
||
}
|
||
return $this->page['deadline'];
|
||
}
|
||
|
||
public static function render_honest_timer( string $label = 'Цены действуют до конца месяца:' ): void {
|
||
$ts = self::instance()->get_honest_deadline();
|
||
if ( $ts <= 0 ) {
|
||
return;
|
||
}
|
||
?>
|
||
<div class="honest-timer" data-deadline="<?php echo (int) $ts; ?>">
|
||
<span class="honest-timer__label"><?php echo esc_html( $label ); ?></span>
|
||
<div class="honest-timer__digits">
|
||
<span class="honest-timer__unit">
|
||
<span class="honest-timer__num" data-timer="d">00</span>
|
||
<span class="honest-timer__unit-label">дн</span>
|
||
</span>
|
||
<span class="honest-timer__sep">:</span>
|
||
<span class="honest-timer__unit">
|
||
<span class="honest-timer__num" data-timer="h">00</span>
|
||
<span class="honest-timer__unit-label">ч</span>
|
||
</span>
|
||
<span class="honest-timer__sep">:</span>
|
||
<span class="honest-timer__unit">
|
||
<span class="honest-timer__num" data-timer="m">00</span>
|
||
<span class="honest-timer__unit-label">мин</span>
|
||
</span>
|
||
<span class="honest-timer__sep">:</span>
|
||
<span class="honest-timer__unit">
|
||
<span class="honest-timer__num" data-timer="s">00</span>
|
||
<span class="honest-timer__unit-label">сек</span>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<?php
|
||
}
|
||
}
|