shkola/wp-content/themes/dekart/inc/class-pksh-data.php
2026-07-18 16:05:15 +00:00

526 lines
19 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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: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'];
}
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 ₽',
'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
}
}