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']; } /** * Email филиала */ 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']; } /** * Город без предлога (например "Щёлково") */ /** * Город в родительном падеже (школы Щёлкова) * Берёт из branch_city_genitive, fallback: city_clean с -о→-а */ 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']; } /** * Социальные сети (из branch_social option или CF) */ 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']; } /** * Логистика — пешком от ТЦ (branch_logistics_walk) */ 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']; } /** * Логистика — парковка (branch_logistics_parking) */ 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']; } /** * Логистика — соседние школы/сад (branch_logistics_schools) */ 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']; } // ============================================================ // HERO / BANNER // ============================================================ /** * ID изображения баннера (hero) */ 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']; } /** * H1 заголовок hero-секции */ 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']; } /** * Подзаголовок hero */ 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']; } /** * Ссылка для * в подзаголовке hero */ 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']; } // ============================================================ // SOCIAL COUNTERS (complex) // ============================================================ /** * Массив social counters (complex field pksh_social_counters) * @return array[] */ 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; } /** * Иконки для social counters (порядок соответствует полю) */ public static function social_icons(): array { return array( 'icon-graduation', 'icon-calendar', 'icon-star-filled', 'icon-teacher' ); } // ============================================================ // PROGRAMS // ============================================================ /** * Данные базовой программы * @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: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']; } /** * Данные премиум-программы * @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: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']; } // ============================================================ // COMPARE TABLE (complex) // ============================================================ /** * Строки таблицы сравнения * @return array[] */ 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) // ============================================================ /** * Массив преподавателей (complex field pksh_teachers) * @return array[] */ 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) // ============================================================ /** * Массив отзывов (complex field pksh_reviews_list) * @return array[] */ 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) // ============================================================ /** * Массив FAQ (complex field pksh_faq_items) * @return array[] */ 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) // ============================================================ /** * Массив фотографий (complex field pksh_gallery) * @return array[] */ 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 (shared helper) // ============================================================ /** * Timestamp честного дедлайна */ 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']; } /** * Вывести HTML честного таймера + inline JS. * Используется в #cta-test и #final-cta. * * @param string $label Текст над таймером. */ public static function render_honest_timer( string $label = 'Цены действуют до конца месяца:' ): void { $ts = self::instance()->get_honest_deadline(); if ( $ts <= 0 ) { return; } ?>
00 дн : 00 ч : 00 мин : 00 сек