_x('Категории курсов', 'taxonomy general name'), 'singular_name' => _x('Категория курсов', 'taxonomy singular name'), 'search_items' => __('Поиск курсов по категории'), 'all_items' => __('Все категории курсов'), 'parent_item' => __('Родительская категория курсов'), 'parent_item_colon' => __('Родителькая категория курсов:'), 'edit_item' => __('Редактировать категорию'), 'update_item' => __('Обновить категорию'), 'add_new_item' => __('Добавить новую категорию'), 'new_item_name' => __('Новая категория'), 'menu_name' => __('Категории курсов'), ); register_taxonomy('courses', array('course'), array( 'hierarchical' => true, 'labels' => $labels, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'courses' ), )); } add_action('init', 'create_course'); function create_course() { register_post_type( 'course', array( 'labels' => array( 'name' => 'Курсы', 'singular_name' => 'Курс', 'add_new' => 'Добавить курс', 'add_new_item' => 'Добавить курс', 'edit' => 'Редактировать курс', 'edit_item' => 'Редактировать курс', 'new_item' => 'Новый курс', 'view' => 'Смотреть курс', 'view_item' => 'Смотреть курс', 'search_items' => 'Поиск курсов', 'not_found' => 'Курсы не найдены', 'not_found_in_trash' => 'В корзине нет курсов', 'parent' => 'Родительский курс' ), 'public' => true, 'exclude_from_search' => false, 'menu_position' => 12, 'supports' => array( 'title' ), 'publicly_queryable' => true, 'menu_icon' => 'dashicons-welcome-learn-more', 'taxonomies' => array( 'courses' ), 'has_archive' => false ) ); } /* --- ##Cources## --- */ /* --- trainingCategory --- */ add_action('init', 'create_trainingCategory_hierarchical_taxonomy', 0); function create_trainingCategory_hierarchical_taxonomy() { $labels = array( 'name' => _x('Категории', 'Категория обучения учителя'), 'singular_name' => _x('Категория', 'Категория'), 'search_items' => __('Поиск категории'), 'all_items' => __('Все категории'), 'parent_item' => __('Родительская категория'), 'parent_item_colon' => __('Родительская категория:'), 'edit_item' => __('Редактировать категорию'), 'update_item' => __('Обновить категорию'), 'add_new_item' => __('Добавить новую категорию'), 'new_item_name' => __('Новая категория'), 'menu_name' => __('Категории'), ); register_taxonomy('trainingCategory', array('teacher'), array( 'hierarchical' => true, 'labels' => $labels, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'rewrite' => false, // Отключаем перезапись URL )); } // ✅ Приоритет 5 — регистрация CPT teacher ДО инициализации Carbon Fields add_action('init', 'create_teacher', 5); function create_teacher() { register_post_type( 'teacher', array( 'labels' => array( 'name' => 'Преподаватели', 'singular_name' => 'Преподаватель', 'add_new' => 'Добавить преподавателя', 'add_new_item' => 'Добавить преподавателя', 'edit' => 'Редактировать преподавателя', 'edit_item' => 'Редактировать преподавателя', 'new_item' => 'Новый преподаватель', 'view' => 'Смотреть преподавателя', 'view_item' => 'Смотреть преподавателя', 'search_items' => 'Поиск преподавателей', 'not_found' => 'Преподаватели не найдены', 'not_found_in_trash' => 'В корзине нет преподавателей', 'parent' => 'Родительский преподаватель' ), 'public' => true, 'exclude_from_search' => false, 'menu_position' => 12, 'show_in_rest' => true, 'supports' => array( 'title', 'thumbnail' ), 'publicly_queryable' => true, 'menu_icon' => 'dashicons-admin-users', 'taxonomies' => array( 'subject' ), 'has_archive' => false ) ); } /* --- ##Teacher## --- */ /* --- Reviews --- */ add_action('init', 'create_reviews'); function create_reviews() { register_post_type( 'reviews', array( 'labels' => array( 'name' => 'Отзывы', 'singular_name' => 'Отзыв', 'add_new' => 'Добавить отзыв', 'add_new_item' => 'Добавить отзыв', 'edit' => 'Редактировать отзыв', 'edit_item' => 'Редактировать отзыв', 'new_item' => 'Новый отзыв', 'view' => 'Смотреть отзыв', 'view_item' => 'Смотреть отзыв', 'search_items' => 'Поиск отзывов', 'not_found' => 'Отзывы не найдены', 'not_found_in_trash' => 'В корзине нет отзывов', 'parent' => 'Родительский отзыв' ), 'public' => true, 'exclude_from_search' => true, 'menu_position' => 13, 'supports' => array( 'title' ), 'publicly_queryable' => false, 'menu_icon' => 'dashicons-format-status', 'has_archive' => false ) ); } use Carbon_Fields\Container; use Carbon_Fields\Field; add_action('carbon_fields_register_fields', 'add_carbon'); function add_carbon() { // ==================================================== // Настройки темы — перегруппировано 2026-07-27 // ==================================================== Container::make('theme_options', 'Настройка темы ДЕКАРТ') ->add_tab('📞 Контакты', array( Field::make('text', 'site_name', 'Название учебного центра') ->set_help_text('Используйте только одинарные кавычки в названии.'), Field::make('text', 'site_phone', 'Телефон'), Field::make('text', 'site_phone_multi', 'Телефон (многоканальный)'), Field::make('text', 'site_mail', 'Почта для связи'), Field::make('text', 'site_index', 'Почтовый индекс'), Field::make('text', 'site_region', 'Область'), Field::make('text', 'site_city', 'Город'), Field::make('text', 'site_address', 'Адрес'), Field::make('text', 'site_map_link', 'Ссылка на карту'), Field::make('text', 'site_location', 'Координаты адреса (для Яндекс.Карт)'), Field::make('text', 'site_lk_url', 'Ссылка на личный кабинет (ЛК)') ->set_default_value('https://lk.dekart-school.ru/') ->set_help_text('URL личного кабинета для учеников/родителей. По умолчанию: https://lk.dekart-school.ru/'), )) ->add_tab('🖥️ Интеграции', array( Field::make('textarea', 'site_bitrix_script', 'Скрипт Bitrix24 (формы)') ->set_help_text('JS-скрипт для форм Bitrix24 на страницах.'), Field::make('textarea', 'site_bitrix_vacancies', 'Скрипт Bitrix24 (форма "Связаться с нами")'), Field::make('textarea', 'site_frame_reviews', 'Код/ссылка iframe для отзывов'), Field::make('html', 'int_banner_sep', '') ->set_html('

🪧 Плашка со скидкой

'), Field::make('checkbox', 'check_banner', 'Показывать плашку со скидкой на формах') ->set_option_value('yes'), Field::make('checkbox', 'check_btn_discont', 'Скрыть кнопку "Стоимость ак. часа со скидкой"') ->set_option_value('yes'), Field::make('text', 'text_banner', 'Текст в плашке') ->set_default_value('Всем записавшимся до 10 сентября
скидка 10% на весь учебный год!'), )) ->add_tab('💳 Цены курсов', array( Field::make('checkbox', 'early_bird_discount', 'Показывать "Скидка за раннюю запись"') ->set_option_value('yes'), Field::make('html', 'price_hours_sep', '') ->set_html('

💰 Полная стоимость

'), Field::make('text', 'price_hour1', '1 предмет') ->set_attribute('type', 'number'), Field::make('text', 'price_hour2', '2 предмета') ->set_attribute('type', 'number'), Field::make('text', 'price_hour3', '3 предмета') ->set_attribute('type', 'number'), Field::make('text', 'price_hour4', '4 и более предметов') ->set_attribute('type', 'number'), Field::make('html', 'price_discount_sep', '') ->set_html('

🏷️ Со скидкой

'), Field::make('text', 'price_hour_discount1', '1 предмет со скидкой') ->set_attribute('type', 'number'), Field::make('text', 'price_hour_discount2', '2 предмета со скидкой') ->set_attribute('type', 'number'), Field::make('text', 'price_hour_discount3', '3 предмета со скидкой') ->set_attribute('type', 'number'), Field::make('text', 'price_hour_discount4', '4 и более предметов со скидкой') ->set_attribute('type', 'number'), )) ->add_tab('🔗 Соцсети', array( Field::make('text', 'social_header_wt', 'WhatsApp — ссылка в шапке сайта'), Field::make('text', 'social_wt', 'WhatsApp — ссылка на странице "Контакты"'), Field::make('complex', 'social_media', 'Другие соцсети') ->add_fields(array( Field::make('text', 'social_media_name', 'Название') ->set_width(100), Field::make('image', 'social_media_img', 'Логотип') ->set_width(20), Field::make('text', 'social_media_link', 'Ссылка') ->set_width(80), )), )) ->add_tab('📸 Галерея', array( Field::make('complex', 'slider_img', 'Изображения учебного центра') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('image', 'img', 'Фотография'), )), )) ->add_tab('📊 SEO + Схема', array( Field::make('html', 'schema_tab_desc', '') ->set_html('

Поля для JSON-LD микроразметки Schema.org. Если поле пусто — свойство не добавляется в @graph. Часть полей дублируется в Настройках филиала (для обратной совместимости).

'), Field::make('html', 'schema_org_sep', '') ->set_html('

🏢 Организация

'), Field::make('text', 'schema_legal_name', 'Юридическое название (legalName)') ->set_width(50) ->set_help_text('Полное юр. название. Например: "ИП Иванов Иван Иванович"'), Field::make('textarea', 'schema_description', 'Описание организации (description)') ->set_width(100) ->set_help_text('Описание для Schema.org Organization → School. Рекомендуется 1–2 предложения.'), Field::make('text', 'schema_postal_code', 'Почтовый индекс (postalCode)') ->set_width(50), Field::make('text', 'schema_founded', 'Год основания (foundingDate)') ->set_width(50) ->set_help_text('Год или дата: "2015" или "2015-09-01".'), Field::make('text', 'schema_map_url', 'Ссылка на карту (hasMap)') ->set_width(100) ->set_help_text('Полная ссылка на Яндекс.Карты или Google Maps.'), Field::make('html', 'schema_hours_sep', '') ->set_html('

🕐 Часы работы

'), Field::make('complex', 'schema_hours', 'График работы (openingHoursSpecification)') ->set_layout('tabbed-horizontal') ->set_help_text('Режим работы на каждый день недели.') ->add_fields(array( Field::make('select', 'day_of_week', 'День недели') ->set_width(30) ->set_options(array( 'Monday' => 'Понедельник', 'Tuesday' => 'Вторник', 'Wednesday' => 'Среда', 'Thursday' => 'Четверг', 'Friday' => 'Пятница', 'Saturday' => 'Суббота', 'Sunday' => 'Воскресенье', )), Field::make('time', 'opens', 'Открытие') ->set_width(25), Field::make('time', 'closes', 'Закрытие') ->set_width(25), Field::make('checkbox', 'day_off', 'Выходной') ->set_width(20) ->set_help_text('Отметьте, если в этот день не работаем.'), )), Field::make('html', 'schema_social_sep', '') ->set_html('

🌐 Социальные сети (sameAs)

'), Field::make('complex', 'schema_social', 'Ссылки на профили') ->set_layout('tabbed-horizontal') ->set_help_text('Ссылки на соцсети для sameAs[] Schema.org.') ->add_fields(array( Field::make('text', 'platform', 'Платформа') ->set_width(30) ->set_help_text('Например: VK, Telegram, YouTube'), Field::make('text', 'url', 'Ссылка') ->set_width(70) ->set_help_text('Полный URL профиля.'), )), Field::make('html', 'schema_media_sep', '') ->set_html('

🖼️ Медиа

'), Field::make('media_gallery', 'schema_photos', 'Фотографии филиала (image[])') ->set_help_text('Фотографии интерьера/экстерьера для image[] в микроразметке.'), Field::make('html', 'schema_area_sep', '') ->set_html('

📍 Регион

'), Field::make('textarea', 'schema_area_served', 'Города присутствия (areaServed)') ->set_width(100) ->set_help_text('Список городов через запятую. Первый город должен совпадать с городом филиала. Влияет на локальный поиск.'), Field::make('html', 'schema_content_sep', '') ->set_html('

📝 Контент

'), Field::make('textarea', 'teachers_block', 'Текст в блоке "Наша команда"'), )); // (пусто — старые поля banner_img_desktop, banner_img_mobile, // banner_h1, banner_text, page_breadcrumbs удалены 31 мая 2026) // ==================================================== // Доп поля для категории Курсов // ==================================================== Container::make('term_meta', 'Дополнительные поля к Курсам') ->where('term_taxonomy', '=', 'courses') ->show_on_level(1) ->where('term_level', '=', 1) ->add_fields(array( Field::make('image', 'snippet', 'Изображение для сниппета:') ->set_width(100), Field::make('image', 'banner_img_desktop', 'Изображение для баннера (десктопная версия)') ->help_text('Размер изображения (желательно) 1920px на 1030px') ->set_width(15), Field::make('image', 'banner_img_mobile', 'Изображение для баннера (мобильная версия)') ->help_text('Размер изображения (желательно) 390px на 550px') ->set_width(15), Field::make('textarea', 'banner_content', 'Текстовый контент баннера') ->set_width(70), Field::make('text', 'title_product', 'Заголовок блока курсов:') ->set_width(100), )); // ==================================================== // Главная Страница — tabbed-horizontal (как pksh) // ==================================================== Container::make('post_meta', 'Настройки Главной Страницы') ->where('post_template', '=', 'front-page.php') ->add_tab('🖼️ HERO', array( Field::make('html', 'front_hero_tab_desc', '') ->set_html('

Фото — квадратное 600×600, в круглой рамке справа.

'), Field::make('image', 'banner_img_desktop', 'Фото') ->set_width(50), Field::make('text', 'banner_h1', 'Заголовок H1') ->set_width(50) ->set_attribute('placeholder', 'Частная школа в Щёлково'), Field::make('html', 'front_hero_stats_sep', '') ->set_html('

📊 Показатели статистики

Добавьте/удалите карточки через +/-.

'), Field::make('complex', 'hero_stats', 'Показатели') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('text', 'stat_number', 'Число') ->set_width(30) ->set_help_text('Например: 12+, 500+, до 12'), Field::make('text', 'stat_label', 'Подпись') ->set_width(70) ->set_help_text('Например: лет опыта, выпускников'), )), )) ->add_tab('📄 О ШКОЛЕ', array( Field::make('text', 'about_school_title', 'Заголовок секции') ->set_default_value('О школе «Декарт»'), Field::make('rich_text', 'block_text_1', 'Текст секции') ->set_help_text('Основной текст о школе. Используйте абзацы, списки, жирный текст.'), )) ->add_tab('👨‍🏫 Преподаватели', array( Field::make('html', 'front_teachers_tab_desc', '') ->set_html('

Секция преподавателей на главной странице. Выберите преподавателей и отредактируйте текст под заголовком.

'), Field::make('textarea', 'front_teachers_text', 'Текст под заголовком') ->set_default_value('Каждый педагог имеет опыт работы с дошкольниками от 5 лет. Все — действующие учителя начальных классов с высшим образованием.') ->set_help_text('Текст описания перед карточками преподавателей.'), Field::make('complex', 'front_teachers', 'Преподаватели на странице') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте преподавателей для главной страницы. Если не добавить ни одного — покажутся все.') ->add_fields(array( Field::make('select', 'teacher_id', 'Выберите преподавателя') ->set_options(array( 0 => '— Выберите преподавателя —' ) + dekart_get_teacher_options()) ->set_width(100) ->set_help_text('ФИО и фото подтянутся из карточки преподавателя.'), )), )) ->add_tab('🎥 Видео-тур', array( Field::make('text', 'front_video_url', 'Ссылка на видео (YouTube/VK)') ->set_help_text('Вставьте ссылку на видео-экскурсию по школе. Если поле пустое — секция не показывается.'), )) ->add_tab('📅 День из жизни', array( Field::make('html', 'front_daylife_desc', '') ->set_html('

Таймлайн «День из жизни ученика». Добавьте 4–6 этапов с фото и текстом.

'), Field::make('complex', 'front_daylife', 'Этапы дня') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('text', 'time', 'Время') ->set_width(20) ->set_help_text('Например: 8:30, 10:00'), Field::make('text', 'title', 'Заголовок') ->set_width(30) ->set_help_text('Например: Зарядка, Уроки, Обед'), Field::make('textarea', 'desc', 'Описание') ->set_width(50), Field::make('image', 'photo', 'Фото') ->set_width(30), )), )) ->add_tab('🌟 Истории успеха', array( Field::make('html', 'front_stories_desc', '') ->set_html('

Персональные кейсы учеников. Добавьте 2–3 истории с фото.

'), Field::make('complex', 'front_stories', 'Истории') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('text', 'student_name', 'Имя ученика') ->set_width(25), Field::make('text', 'age', 'Возраст / класс') ->set_width(15), Field::make('textarea', 'problem', 'Проблема / запрос') ->set_width(60), Field::make('textarea', 'result', 'Результат / достижение') ->set_width(60), Field::make('image', 'photo', 'Фото (до/после)') ->set_width(30) ->set_help_text('Фото ребёнка (с согласия родителей)'), )), )) ->add_tab('❓ FAQ', array( Field::make('complex', 'front_faq', 'Вопросы и ответы') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте частые вопросы родителей. Если не добавить ни одного — секция не покажется.') ->add_fields(array( Field::make('text', 'faq_question', 'Вопрос') ->set_width(30), Field::make('textarea', 'faq_answer', 'Ответ') ->set_width(70), )), )) ->add_tab('💰 Стоимость', array( Field::make('html', 'front_price_desc', '') ->set_html('

Карточки стоимости обучения. Добавьте для каждого класса/программы свою карточку с ценой и списком критериев.

'), Field::make('complex', 'price_cards', 'Карточки стоимости') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте карточки для каждого класса (например: «Начальная школа», «Подготовка к школе», «Продлёнка»). Если не добавить ни одной — секция не покажется.') ->add_fields(array( Field::make('text', 'class_name', 'Название класса / программы') ->set_width(30) ->set_help_text('Например: «Начальная школа (1–4 класс)»'), Field::make('text', 'price', 'Стоимость') ->set_width(30) ->set_help_text('Например: «от 25 000 ₽/мес»'), Field::make('textarea', 'features', 'Критерии (по одному на строку)') ->set_width(40) ->set_help_text('Каждая строка — отдельный критерий с галочкой. Пример для начальной школы:

Классы до 10 человек
Уроки до 13:00, продлёнка до 19:00
Продлёнка: обед, полдник, ДЗ, кружки
Английский язык с 1 класса
Лицензия Минобр МО
Помощь с домашними заданиями
Спортивные и творческие кружки

Пример для продлёнки:

Присмотр с 12:00 до 19:00
Горячий обед и полдник
Помощь с уроками
Прогулки на свежем воздухе
Творческие занятия'), )), )) ->add_tab('📊 Сравнение', array( Field::make('html', 'front_compare_desc', '') ->set_html('

Таблица сравнения «Декарт vs Государственная школа». Каждая строка — отдельная запись. Порядок = порядок вывода.

'), Field::make('text', 'compare_header_param', 'Заголовок колонки «Параметр»') ->set_width(33) ->set_default_value('Параметр'), Field::make('text', 'compare_header_dekart', 'Заголовок колонки «Декарт»') ->set_width(33) ->set_default_value('🎓 «Декарт»'), Field::make('text', 'compare_header_state', 'Заголовок колонки «Гос. школа»') ->set_width(33) ->set_default_value('📚 Государственная'), Field::make('complex', 'compare_rows', 'Строки сравнения') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте строки сравнения. Для каждой строки: параметр, текст для Декарт, текст для государственной школы.') ->add_fields(array( Field::make('text', 'param', 'Параметр') ->set_width(100) ->set_help_text('Название параметра, например: «Число учеников в классе»'), Field::make('html', 'compare_dekart_sep', '') ->set_html('

🔸 Декарт

'), Field::make('textarea', 'dekart', 'Текст (Декарт)') ->set_width(100) ->set_help_text('Текст для колонки «Декарт» с галочкой. Например: «До 10 человек — малые классы»'), Field::make('html', 'compare_state_sep', '') ->set_html('

🔸 Государственная школа

'), Field::make('textarea', 'state', 'Текст (Гос. школа)') ->set_width(100) ->set_help_text('Текст для колонки «Государственная школа» с крестиком. Например: «30–35 человек»'), )), )) ->add_tab('💬 Слово руководителю', array( Field::make('html', 'front_expert_desc', '') ->set_html('

Блок цитаты руководителя школы для повышения доверия (E-E-A-T).

'), Field::make('textarea', 'expert_quote_text', 'Текст цитаты') ->set_width(100) ->set_help_text('Основная цитата руководителя. Если поле пустое — блок не показывается.'), Field::make('text', 'expert_quote_author', 'Имя руководителя') ->set_width(50) ->set_help_text('Оставьте пустым, чтобы использовать имя из Настроек филиала.'), Field::make('text', 'expert_quote_role', 'Должность / регалии') ->set_width(50) ->set_help_text('Оставьте пустым, чтобы использовать данные из Настроек филиала.'), Field::make('image', 'expert_quote_photo', 'Фото руководителя') ->set_width(50) ->set_help_text('Оставьте пустым, чтобы использовать фото из Настроек филиала. Рекомендуемый размер: 200×200px.'), Field::make('text', 'expert_quote_title', 'Заголовок секции') ->set_width(50) ->set_default_value('Почему родители выбирают «Декарт»'), Field::make('textarea', 'expert_quote_subtitle', 'Подзаголовок секции') ->set_width(50) ->set_default_value('Руководитель школы делится ценностями и подходом к обучению'), )) ->add_tab('👁️ Видимость секций', array( Field::make('html', 'front_visibility_desc', '') ->set_html('

Включите/отключите показ секций на главной странице. Секции HERO, КОНТАКТЫ и Sticky CTA — всегда показаны.

'), Field::make('checkbox', 'section_visible_services', '📋 Услуги') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_comparison', '📊 Сравнение') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_faq', '❓ FAQ') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_video', '🎥 Видео-тур') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_daylife', '📅 День из жизни') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_stories', '🌟 Истории успеха') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_cta', '📞 CTA-консультация') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_reviews', '⭐ Отзывы / ссылка') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_teachers', '👨‍🏫 Преподаватели') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_expert_quotes', '💬 Слово руководителю') ->set_option_value('yes') ->set_default_value('yes'), Field::make('checkbox', 'section_visible_price', '💰 Стоимость (price cards)') ->set_option_value('yes') ->set_default_value('yes'), )); // ==================================================== // Доп поля для страницы начальной школы // ==================================================== Container::make('post_meta', 'Настройки Начальной Школы') ->where('post_template', '=', 'page-school.php') ->add_fields(array( Field::make('textarea', 'teachers_block', 'Текст в блоке "Наша команда":'), Field::make('textarea', 'block_text_1', 'Текст для блока "Персональный план развития для каждого ученика"'), Field::make('textarea', 'block_text_2', 'Текст для блока - Почему начальная частная школа "Декарт", ‌а не государственная?'), Field::make('textarea', 'block_text_3', 'Текст для блока "Семейные классы в Щелково"'), Field::make('complex', 'questions', 'Блок вопросы и ответы') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('textarea', 'questions_question', 'Текст вопроса') ->set_width(30), Field::make('textarea', 'questions_answer', 'Текст ответа') ->set_width(70), )), )); // ==================================================== // Доп поля для страницы "ВСЕ КУРСЫ" // ==================================================== Container::make('post_meta', 'Настройки Страницы Все Курсы') ->where('post_template', '=', 'page-course.php') ->add_fields(array( Field::make('image', 'banner_img_desktop', 'Изображение для баннера (десктопная версия)') ->help_text('Размер изображения (желательно) 1920px на 440px') ->set_width(15), Field::make('image', 'banner_img_mobile', 'Изображение для баннера (мобильная версия)') ->help_text('Размер изображения (желательно) 450px на 225px') ->set_width(15), )); // ==================================================== // Доп поля для страницы "ВАКАНСИИ" // ==================================================== Container::make('post_meta', 'Настройки Страницы ВАКАНСИИ') ->where('post_template', '=', 'page-vacancies.php') ->add_fields(array( Field::make('complex', 'vacancies', 'Вакансии учебного центра:') ->add_fields(array( Field::make('text', 'vacancie_name', 'Название вакансии:'), Field::make('text', 'vacancie_link', 'Ссылка на страницу вакансии:'), )) )); // ==================================================== // Доп поля для страницы "КОНТАКТЫ" // ==================================================== Container::make('post_meta', 'Настройки Страницы Контакты') ->where('post_template', '=', 'page-contacts.php') ->add_fields(array( Field::make('image', 'img_school', 'Изображение школы:') )); // ==================================================== // Доп поля для категории (ПРЕДМЕТ) // ==================================================== Container::make('term_meta', 'Category Properties') ->where('term_taxonomy', '=', 'subject') ->show_on_level(1) ->where('term_level', '=', 1) ->add_fields(array( Field::make('text', 'subject_h1', 'Заголовок H1:') ->set_width(100) )); // ==================================================== // Доп поля для сущностей reviews (ОТЗЫВ) // ==================================================== Container::make('post_meta', 'Поля для отзыва') ->where('post_type', '=', 'reviews') ->add_fields(array( Field::make('radio', 'review_type', 'Тип отзыва') ->set_options([ 'camp' => 'О лагере', 'school' => 'О школе', 'primary' => 'О начальной школе', ]) ->set_default_value('school') ->set_help_text('Выберите тип отзыва'), Field::make('image', 'review_avatar', 'Автар:') ->set_width(15), Field::make('text', 'review_star', 'Оценка:') ->set_attribute('type', 'number'), Field::make('textarea', 'review_text', 'Текст отзыва:') ->set_width(100), Field::make('date', 'review_date', 'Дата отзыва') ->set_storage_format('d.m.Y') ->set_input_format('d.m.Y', 'd.m.Y') ->set_picker_options(array( 'altInput' => false, )) ->set_help_text('Дата отзыва. Формат: ДД.ММ.ГГГГ'), Field::make('association', 'review_teacher', 'Выберите преподавателя:') ->set_width(32) ->set_types(array( array( 'type' => 'post', 'post_type' => 'teacher', ) )) ->set_required(true) ->set_max(1) ->help_text('выбирается только один'), Field::make('checkbox', 'review_show_on_front', 'Показывать на главной') ->set_option_value('yes') ->set_help_text('Отметьте, чтобы отзыв отображался в секции отзывов на главной странице'), )); // ==================================================== // Доп поля для записей teacher // ==================================================== Container::make('post_meta', 'Поля для преподавателя') ->where('post_type', '=', 'teacher') ->add_fields(array( Field::make('text', 'teacher_direction', 'Направление преподавателя (текст в под фото):'), Field::make('text', 'teacher_badge', 'Бейдж на карточке (например: 👶 Работает с дошкольниками)') ->set_width(30) ->set_help_text('Текст бейджа на карточке преподавателя. Если пусто — бейдж скрыт.'), Field::make('image', 'teacher_avatar', 'Аватар:') ->set_width(15), Field::make('text', 'teacher_start_year', 'Год начала работы (только год, например: 1987)') ->set_width(30) ->set_attribute('placeholder', '1987') ->set_help_text('Стаж рассчитается автоматически на странице подготовки к школе.'), Field::make('textarea', 'teacher_description', 'Дескрипшн преподавателя') ->set_width(55), Field::make('textarea', 'teacher_about', 'О себе:'), Field::make('textarea', 'teacher_education', 'Образование:'), Field::make('textarea', 'teacher_add_education', 'Дополнительное образование:'), Field::make('text', 'teacher_rating', 'Оценка преподавателя') ->set_width(10) ->set_default_value('5'), Field::make('complex', 'teacher_subjects', 'Предметы обучения') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('text', 'teacher_subjects_title', 'Укажите заголовок предмета') ->set_width(50) ->set_required(true) ->help_text('Например: Репетитор по математике'), Field::make('textarea', 'select_direction', 'Укажите все направления преподавателя:') ->help_text('Пример: <span>Математика</span><span>Русский язык</span>'), Field::make('association', 'select_category', 'Укажите категрии') ->set_width(100) ->set_types(array( array( 'type' => 'term', 'taxonomy' => 'trainingCategory', ) )) ->help_text('В списке указаны все возможные категрии в обучении, выберите необходимые'), )), Field::make('complex', 'certificates', 'Дипломы и сертификаты') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('image', 'certificates_foto', 'Изображение') )) ->help_text('Добавьте изображение дипломов и сертификатов преподавателя'), Field::make('text', 'teacher_video', 'Ссылка на видеопрезентацию') ->set_width(100) ->help_text('Укажите ссылку на видео в youtube. Пример: <iframe src="https://vk.com/video_ext.php?oid=-43228812&id=456240170hd=2" width="853" height="480" allow="autoplay; encrypted-media; fullscreen; picture-in-picture;" frameborder="0" allowfullscreen></iframe>'), Field::make('complex', 'questions', 'Блок вопросы и ответы') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('textarea', 'questions_question', 'Текст вопроса') ->set_width(30), Field::make('textarea', 'questions_answer', 'Текст ответа') ->set_width(70), )), )); // ==================================================== // Доп поля для страницы "Подготовка к школе (Bento 2026)" // ==================================================== Container::make('post_meta', 'Настройки Подготовки к школе') ->where('post_template', '=', 'page-podgotovka-k-shkole.php') ->add_tab('🖼️ Герой (баннер)', array( Field::make('html', 'pksh_hero_tab_desc', '') ->set_html('

Секция: .hero-pksh. Первый экран страницы подготовки к школе.

'), Field::make('image', 'banner_image', 'Фото баннера') ->set_width(50) ->set_help_text('Рекомендуемый размер: 689×689 px, квадратное. Если не указано — используется фото по умолчанию.'), Field::make('text', 'banner_h1', 'Заголовок H1') ->set_width(50) ->set_default_value('Ваш ребёнок готов к первому классу? Научим читать, считать и писать за 4 месяца — без слёз и стресса') ->set_help_text('Главный заголовок на первом экране.'), Field::make('textarea', 'banner_subtitle', 'Подзаголовок') ->set_width(50) ->set_default_value('Первое занятие — бесплатно. Результат через 3 недели — или вернём деньги') ->set_help_text('Текст под заголовком. Опционально.'), Field::make('text', 'banner_subtitle_footnote_link', 'Ссылка для звёздочки (*) в подзаголовке') ->set_width(50) ->set_help_text('URL для иконки * после текста подзаголовка. Если не указано — * неактивна.'), Field::make('text', 'banner_scarcity', 'Текст дефицита (срочность)') ->set_width(50) ->set_default_value('🔥 Осталось 2 места из 8 в группе 5–6 лет. Стартуем 1 июня') ->set_help_text('Можно использовать HTML-теги: <strong>, <br>. Текст о срочности/дефиците мест под кнопкой.'), Field::make('textarea', 'pksh_hero_definition', 'Определение для AI (первые 60 слов)') ->set_rows(3) ->set_help_text( '📖 Для AI-поиска (GEO). Текст, который AI использует для ответа на «Что такое подготовка к школе в [городе]?». ' . 'Рекомендуется 40–60 слов, начинается с «Подготовка к школе в [городе] — это…». ' . 'Выводится на странице после H1, перед подзаголовком. Если не заполнено — блок скрыт.' ) ->set_default_value('Подготовка к школе в Щёлково — это комплексные занятия для детей 5–7 лет, которые помогают освоить чтение, письмо, счёт и развить логическое мышление. Программа построена на игровой методике: ребёнок учится без стресса, в комфортном темпе. Группы до 10 человек, индивидуальный подход к каждому.'), )) ->add_tab('📊 Соц.доказательство', array( Field::make('html', 'pksh_social_tab_desc', '') ->set_html('

Секция: .social-counters. Блок цифр социального доказательства (4 карточки). Иконки заданы в шаблоне, здесь только текст.

'), Field::make('complex', 'pksh_social_counters', 'Показатели') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте до 4 показателей. Порядок = порядок вывода. Иконки не редактируются.') ->add_fields(array( Field::make('text', 'counter_number', 'Число') ->set_width(30) ->set_help_text('Например: 500+, 12, 4.8, 20+'), Field::make('text', 'counter_label', 'Подпись') ->set_width(70) ->set_help_text('Например: выпускников в топ-школах'), )), Field::make('html', 'pksh_social_author_header', '') ->set_html('

👤 Автор контента (E-E-A-T для SEO)

Эти поля влияют на E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) — фактор ранжирования Google. Указываются в микроразметке Schema.org и отображаются в блоке автора внизу страницы. Заполните, чтобы повысить доверие поисковых систем к контенту.

'), Field::make('text', 'pksh_author_name', 'Имя автора контента') ->set_width(50) ->set_default_value('Частная школа «Декарт»') ->set_help_text( 'Для SEO: Имя автора для Schema.org Person / author. ' . 'Рекомендуется: фактическое название организации или ФИО руководителя/педагога. ' . 'Влияет на E-E-A-T — Google проверяет автора контента. ' . 'По умолчанию: название из поля «Название филиала» в Настройках темы.' ), )) ->add_tab('⭐ Отзывы', array( Field::make('html', 'pksh_reviews_tab_desc', '') ->set_html('

Секция: .pksh-reviews. Отзывы родителей на странице подготовки к школе.

'), Field::make('complex', 'pksh_reviews_list', 'Отзывы') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте отзывы родителей. Показываются на странице подготовки к школе.') ->add_fields(array( Field::make('image', 'review_avatar', 'Аватар') ->set_width(15) ->set_help_text('Опционально. Если не указано — генерируется из имени.'), Field::make('text', 'review_author', 'Имя автора') ->set_width(25), Field::make('text', 'review_rating', 'Оценка (1–5)') ->set_width(10) ->set_attribute('type', 'number'), Field::make('date', 'review_date', 'Дата отзыва') ->set_width(15) ->set_storage_format('d.m.Y') ->set_input_format('d.m.Y', 'd.m.Y') ->set_picker_options(array( 'altInput' => false )) ->set_help_text('Для Schema.org Review.datePublished. Формат: ДД.ММ.ГГГГ'), Field::make('association', 'review_teacher', 'Преподаватель') ->set_width(25) ->set_types(array( array( 'type' => 'post', 'post_type' => 'teacher', ), )) ->set_max(1) ->set_help_text('Если родитель хвалит конкретного учителя — привяжите отзыв к нему. Необязательно.'), Field::make('textarea', 'review_text', 'Текст отзыва') ->set_width(35), )), )) ->add_tab('❓ FAQ', array( Field::make('html', 'pksh_faq_tab_desc', '') ->set_html('

Секция: #pksh-faq. Вопросы и ответы в стиле лагеря, две колонки.

'), Field::make('complex', 'pksh_faq_items', 'Вопросы и ответы') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте вопросы и ответы. Показываются в секции FAQ на странице подготовки к школе.') ->add_fields(array( Field::make('textarea', 'faq_question', 'Вопрос') ->set_width(30), Field::make('textarea', 'faq_answer', 'Ответ') ->set_width(70), )), )) ->add_tab('👨‍🏫 Преподаватели', array( Field::make('html', 'pksh_teachers_tab_desc', '') ->set_html('

Секция: #teachers. Выберите преподавателей из добавленных в разделе Преподаватели главного меню админки. ФИО и фото берутся из карточки преподавателя.

'), Field::make('textarea', 'pksh_teachers_text', 'Текст под заголовком') ->set_default_value('Каждый педагог имеет опыт работы с дошкольниками от 5 лет. Все — действующие учителя начальных классов с высшим образованием.') ->set_help_text('Текст описания перед карточками преподавателей.'), Field::make('complex', 'pksh_teachers', 'Преподаватели на странице') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте преподавателей для этой страницы. Выберите из списка существующих.') ->add_fields(array( Field::make('select', 'teacher_id', 'Выберите преподавателя') ->set_options(array( 0 => '— Выберите преподавателя —' ) + dekart_get_teacher_options()) ->set_width(100) ->set_help_text('ФИО и фото подтянутся из карточки преподавателя. Если нужного нет — добавьте в разделе Преподаватели.'), )), )) // ==================================================== // Вкладка: Программы подготовки к школе // ==================================================== ->add_tab('📚 Программы', array( Field::make('html', 'pksh_programs_tab_desc', '') ->set_html('

Секция: #programs. Две фиксированные карточки: базовая и расширенная программа.

'), Field::make('html', 'pksh_prog_base_title', '') ->set_html('

🔵 Базовая — «Уверенный старт»

'), Field::make('text', 'pksh_prog_base_name', 'Название программы') ->set_width(100) ->set_default_value('Уверенный старт'), Field::make('text', 'pksh_prog_base_subname', 'Подзаголовок') ->set_width(100) ->set_default_value('2 раза в неделю — комфортный темп без перегрузки'), Field::make('text', 'pksh_prog_base_schedule', 'Расписание') ->set_width(100) ->set_default_value('вт, чт — 18:00–19:30'), Field::make('text', 'pksh_prog_base_price_sub', 'Стоимость абонемента за 4 недели') ->set_width(50) ->set_default_value('7 500 ₽'), 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 места в группе'), Field::make('html', 'pksh_prog_prem_title', '') ->set_html('

🟣 Расширенная — «Результат за 3 месяца»

'), Field::make('text', 'pksh_prog_prem_name', 'Название программы') ->set_width(100) ->set_default_value('Результат за 3 месяца'), Field::make('text', 'pksh_prog_prem_subname', 'Подзаголовок') ->set_width(100) ->set_default_value('3 раза в неделю — быстрый прогресс'), Field::make('text', 'pksh_prog_prem_schedule', 'Расписание') ->set_width(100) ->set_default_value('пн, ср, пт — 16:30–18:00'), Field::make('text', 'pksh_prog_prem_price_sub', 'Стоимость абонемента за 4 недели') ->set_width(50) ->set_default_value('10 500 ₽'), 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 места в группе'), )) // ==================================================== // Вкладка: Сравнение (Как мы отличаемся) // ==================================================== ->add_tab('📊 Как мы отличаемся', array( Field::make('html', 'pksh_compare_tab_desc', '') ->set_html('

Секция: .pksh-compare. Таблица сравнения Декарт vs Репетитор vs Кружок. Каждая строка — отдельная запись. Порядок = порядок вывода.

'), Field::make('complex', 'pksh_compare_rows', 'Строки таблицы') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте строки сравнения. Для каждой строки: критерий, текст для трёх колонок, иконка ✓/✗ для каждой колонки.') ->add_fields(array( Field::make('text', 'criteria', 'Критерий') ->set_width(100) ->set_help_text('Название строки, например: «Гослицензия»'), Field::make('html', 'pksh_compare_dekart_header', '') ->set_html('

🔸 Декарт

'), Field::make('select', 'dekart_icon', 'Иконка') ->set_width(20) ->set_options(array( '' => '— нет —', 'yes' => '✓ (да)', 'no' => '✗ (нет)', )), Field::make('textarea', 'dekart_text', 'Текст') ->set_width(80) ->set_help_text('Например: «Есть»'), Field::make('html', 'pksh_compare_repetitor_header', '') ->set_html('

🔸 Репетитор

'), Field::make('select', 'repetitor_icon', 'Иконка') ->set_width(20) ->set_options(array( '' => '— нет —', 'yes' => '✓ (да)', 'no' => '✗ (нет)', )), Field::make('textarea', 'repetitor_text', 'Текст') ->set_width(80), Field::make('html', 'pksh_compare_kruzhok_header', '') ->set_html('

🔸 Обычный кружок

'), Field::make('select', 'kruzhok_icon', 'Иконка') ->set_width(20) ->set_options(array( '' => '— нет —', 'yes' => '✓ (да)', 'no' => '✗ (нет)', )), Field::make('textarea', 'kruzhok_text', 'Текст') ->set_width(80), )), Field::make('textarea', 'pksh_compare_footnote', 'Сноска под таблицей') ->set_help_text('Текст под таблицей. Можно использовать HTML.') ->set_default_value('Важно: Данные по репетиторам и кружкам — рыночная оценка по городу и требует уточнения.'), )) // ==================================================== // Вкладка: JSON-LD Schema (данные для микроразметки) // ==================================================== ->add_tab('🧠 JSON-LD (схема)', array( Field::make('html', 'pksh_schema_tab_desc', '') ->set_html('

Поля для JSON-LD микроразметки Schema.org. Заполняются опционально — если поле пусто, свойство не добавляется в граф.

'), Field::make('textarea', 'pksh_description', 'Описание курса (для микроразметки)') ->set_help_text( 'Подробное описание программы для Schema.org Course.description. ' . 'Если заполнено — заменяет banner_subtitle в микроразметке. ' . 'Рекомендуется минимум 150 символов. НЕ влияет на отображение страницы.' ) ->set_rows(4) ->set_attribute('placeholder', 'Комплексная программа подготовки детей 5–7 лет к первому классу...'), Field::make('text', 'pksh_level', 'Уровень образования (educationalLevel)') ->set_width(50) ->set_help_text('Например: "дошкольное образование" или "5-7 лет"'), Field::make('text', 'pksh_age', 'Возраст детей') ->set_width(50) ->set_help_text('Например: "5–7 лет"'), Field::make('text', 'pksh_audience', 'Целевая аудитория (audience)') ->set_help_text('Например: "Дети 5–7 лет, будущие первоклассники"'), Field::make('select', 'pksh_course_mode', 'Формат обучения (courseMode)') ->set_width(50) ->set_help_text('Формат занятий для Schema.org CourseInstance.courseMode.') ->add_options(array( '' => '— выберите —', 'Onsite' => 'Очно (в центре)', 'Online' => 'Онлайн', 'Blended' => 'Смешанный (очно + онлайн)', )), Field::make('complex', 'pksh_skills', 'Чему учат на курсе') ->set_layout('tabbed-horizontal') ->set_help_text('Навыки, которые освоит ребёнок. Каждая запись — отдельный навык (дисциплина).') ->add_fields(array( Field::make('text', 'skill', 'Навык / дисциплина') ->set_width(100) ->set_attribute('placeholder', 'Чтение, Счёт до 100, Письмо печатными буквами') ->set_help_text('Например: "Чтение", "Счёт до 100", "Письмо печатными буквами"'), )), )) // ==================================================== // Вкладка: GEO / AI-поиск (self-contained answer блоки для цитирования) // ==================================================== ->add_tab('🤖 GEO (AI-поиск)', array( Field::make('html', 'pksh_geo_tab_desc', '') ->set_html('

Поля для Generative Engine Optimization — контент, оптимизированный для цитирования AI-поиском (Google AI Overviews, ChatGPT, Perplexity). Каждый блок должен быть самодостаточным (134–167 слов) и содержать конкретные данные.

'), Field::make('html', 'pksh_geo_questions_title', '') ->set_html('

❓ Вопросы-заголовки для AI

'), Field::make('html', 'pksh_geo_questions_desc', '') ->set_html('

Эти заголовки (H2/H3) отвечают на типичные поисковые запросы. AI видит их как прямые ответы. Если поле пусто — секция не выводится.

'), Field::make('text', 'pksh_geo_q1', 'Вопрос-заголовок #1') ->set_width(100) ->set_help_text('Например: «Сколько стоит подготовка к школе в Щёлково?»') ->set_default_value('Сколько стоит подготовка к школе в Щёлково?'), Field::make('text', 'pksh_geo_q2', 'Вопрос-заголовок #2') ->set_width(100) ->set_help_text('Например: «Что должен знать ребёнок перед школой?»') ->set_default_value('Что должен знать ребёнок перед школой?'), Field::make('text', 'pksh_geo_q3', 'Вопрос-заголовок #3') ->set_width(100) ->set_help_text('Например: «Как выбрать центр подготовки к школе?»') ->set_default_value('Как выбрать центр подготовки к школе?'), Field::make('html', 'pksh_geo_answers_title', '') ->set_html('

📝 Answer-блоки для AI-цитирования

'), Field::make('html', 'pksh_geo_answers_desc', '') ->set_html('

Каждый блок — 134–167 слов, самодостаточный, с конкретными данными. AI может процитировать его целиком. Рекомендуется: факты, цифры, сроки, цены. Если поле пусто — блок не выводится.

'), Field::make('textarea', 'pksh_geo_answer_programs', 'Answer-блок: Программы и цены') ->set_rows(8) ->set_help_text( 'Выводится в секции Программы перед карточками. ' . 'Рекомендуется 134–167 слов. Опишите программы, цены, разницу между базовой и расширенной.' ) ->set_default_value( 'В детском центре «Декарт» в Щёлково действуют две программы подготовки к школе. Базовая программа «Уверенный старт» включает 2 занятия в неделю по 30–40 минут — стоимость абонемента 7 500 ₽ в месяц. Расширенная программа «Результат за 3 месяца» — 3 занятия в неделю, 10 500 ₽ в месяц. Обе программы ведут действующие педагоги начальных классов со стажем от 12 лет. Группы до 10 человек — каждому ребёнку уделяется внимание. Первое занятие — бесплатно, без договора и оплаты. В стоимость включены все учебные материалы и пособия. Занятия проходят очно по адресу: Талсинская ул., 24. Результат через 3 недели — дети начинают читать по слогам.' ), Field::make('textarea', 'pksh_geo_answer_results', 'Answer-блок: Результаты и статистика') ->set_rows(8) ->set_help_text( 'Выводится в секции Результаты. ' . 'Рекомендуется 134–167 слов. Конкретные цифры, проценты, сроки.' ) ->set_default_value( '95% выпускников центра «Декарт» поступают в школы и лицеи Щёлкова без стресса — они готовы к учебной нагрузке и требованиям учителей. Первые результаты заметны уже через 3 недели: нечитавшие дети складывают первый осмысленный слог. 87% родителей отмечают рост самостоятельности ребёнка после месяца занятий. Выпускники центра адаптируются в первом классе в 2,5 раза быстрее сверстников — они не боятся отвечать у доски, поднимать руку и работать в коллективе. За 12 лет работы центром подготовлено более 500 детей. Программа построена так, что каждый ребёнок осваивает чтение, письмо, счёт и логику без перегрузки — занятия длятся 30–40 минут, каждые 7 минут смена активности.' ), Field::make('textarea', 'pksh_geo_answer_howitworks', 'Answer-блок: Как проходят занятия') ->set_rows(8) ->set_help_text( 'Выводится в секции Как проходят занятия. ' . 'Рекомендуется 134–167 слов. Опишите методику, длительность, структуру.' ) ->set_default_value( 'Каждое занятие длится 30–40 минут и построено так, чтобы ребёнок не уставал. Активность меняется каждые 7 минут — это оптимальный интервал удержания внимания для детей 5–7 лет. Урок начинается с короткой истории или загадки, которая вводит в тему и включает интерес. Затем следует игровое задание: чтение через игру, счёт через механику соревнования, логика через головоломки. После каждого блока — активная перемена с нейрогимнастикой. Завершается занятие рефлексией: ребёнок сам рассказывает, чему научился. Все педагоги имеют высшее педагогическое образование и опыт работы с дошкольниками от 5 лет. Методика исключает скучные прописи и многочасовое сидение за партой — дети воспринимают занятия как игру и с удовольствием возвращаются.' ), )) // ==================================================== // Вкладка: Фотогалерея // ==================================================== ->add_tab('📸 Фотогалерея', array( Field::make('html', 'pksh_gallery_tab_desc', '') ->set_html('

Секция: #gallery. Фотографии занятий, 3 в ряд. Если фото не добавлены — секция не выводится.

'), Field::make('complex', 'pksh_gallery', 'Фотографии') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте фотографии с занятий. Оптимальная ширина: 600–1200 px.') ->add_fields(array( Field::make('image', 'gallery_image', 'Фото') ->set_width(60) ->set_help_text('Рекомендуемый размер: 800×600 px, соотношение 4:3 или 3:2.'), Field::make('text', 'gallery_caption', 'Подпись (опционально)') ->set_width(40) ->set_help_text('Короткая подпись под фото. Если не указана — только фото.'), )), )); // ==================================================== // Контейнер: Программа Подготовки к школе (служебная страница) // ==================================================== Container::make('post_meta', '📄 Программа «Подготовка к школе»') ->where('post_template', '=', 'page-program-pksh.php') ->add_fields(array( Field::make('html', 'pksh_prog_header', '') ->set_html('

Официальный документ — образовательная программа подготовки к школе. Текст программы менять нельзя — это утверждённый документ. Для обновления скопируйте новый текст целиком.

'), Field::make('rich_text', 'pksh_prog_content', 'Текст программы') ->set_help_text( 'ВАЖНО: Это официально утверждённый документ. Не меняйте содержание. ' . 'Для обновления — замените текст целиком на новую версию. ' . 'Рекомендуется вставлять из Google Docs / Word без форматирования, ' . 'затем применить заголовки H2-H3 и списки вручную.' ), Field::make('html', 'pksh_prog_legal_header', '') ->set_html('

⚖️ Юридическая информация

'), Field::make('date', 'pksh_prog_doc_date', 'Дата утверждения / обновления документа') ->set_width(30) ->set_storage_format('Y-m-d') ->set_input_format('Y-m-d', 'Y-m-d') ->set_help_text('Дата последнего утверждения или обновления программы (YYYY-MM-DD). Отображается в дисклеймере.'), Field::make('textarea', 'pksh_prog_disclaimer', 'Текст дисклеймера') ->set_width(100) ->set_default_value( 'Электронная версия программы предназначена для ознакомления. При переносе в электронный вид ' . 'возможны технические неточности (опечатки, ошибки форматирования). ' . 'Юридически значимым считается документ, предоставленный в офисе организации. ' . 'Дата последнего обновления электронной версии:' ) ->set_rows(4) ->set_help_text('Текст, который выводится в блоке дисклеймера. Можно редактировать независимо от текста программы.'), Field::make('html', 'pksh_prog_service_header', '') ->set_html('

🔗 Ссылка на услугу

'), Field::make('text', 'pksh_prog_service_url', 'URL услуги') ->set_width(50) ->set_default_value('/podgotovka-k-shkole/') ->set_help_text('Ссылка на страницу услуги, которая реализует данную программу.'), Field::make('text', 'pksh_prog_service_label', 'Текст ссылки') ->set_width(50) ->set_default_value('Записаться на подготовку к школе') ->set_help_text('Текст кнопки/ссылки для перехода на услугу.'), )); // ==================================================== // Уникальное имя контейнера Продлёнки // ==================================================== Container::make('post_meta', 'Настройки Продлёнки') ->where('post_template', '=', 'page-after-school.php') ->add_tab('Общие', array( Field::make('text', 'as_address', 'Наш адрес:'), Field::make('text', 'as_price', 'Цена:'), )) ->add_tab('Педагоги', array( Field::make('complex', 'as_mentors', 'Педагоги') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('image', 'mentor_foto', 'Фотография:') ->set_width(15), Field::make('text', 'mentor_name', 'ФИО:') ->set_width(30), Field::make('text', 'mentor_directions', 'Описание:') ->set_width(55), )) )) ->add_tab('Распорядок дня', array( Field::make('textarea', 'as_routine', 'Блок "Распорядок дня":'), )) ->add_tab('Отзывы', array( Field::make('complex', 'as_reviews', 'Отзывы клиентов:') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('image', 'review_avatar', 'Автар:') ->set_width(15), Field::make('text', 'review_name', 'Имя:') ->set_width(30), Field::make('text', 'review_star', 'Оценка:') ->set_width(15) ->set_attribute('type', 'number'), Field::make('textarea', 'review_text', 'Текст отзыва:') ->set_width(100), )), )) ->add_tab('Вопросы-Ответы', array( Field::make('complex', 'as_questions', 'Блок вопросы и ответы') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('textarea', 'questions_question', 'Текст вопроса') ->set_width(30), Field::make('textarea', 'questions_answer', 'Текст ответа') ->set_width(70), )), )) ->add_tab('Фото', array( Field::make('complex', 'as_fotos', 'Фотографии:') ->set_layout('tabbed-horizontal') ->add_fields(array( Field::make('image', 'foto', 'Фото') )), )) ->add_tab('Битрикс', array( Field::make('textarea', 'as_bitrix_script', 'script (формы) БИТРИКС24:'), )); // ==================================================== // Доп поля для страницы "ГОРОДСКОЙ ЛАГЕРЬ" // ==================================================== Container::make('post_meta', '🏰 Настройки Городской Лагерь') ->where('post_template', '=', 'page-camp.php') ->add_tab('🖼️ Первый экран', array( Field::make('html', 'hero_tab_desc', '') ->set_html('

Шаблон: page-camp.php · Секция: .hero-media-search

'), Field::make('separator', 'hero_media_sep', 'Изображения'), Field::make('image', 'banner_img', 'Фото на весь экран (десктоп)') ->set_help_text('Оптимально: 1920×1080 px, WebP/JPG. Дети в движении, эмоции.') ->set_width(50), Field::make('separator', 'hero_titles_sep', 'Заголовки и текст'), Field::make('text', 'hero_title_h1', 'Заголовок H1') ->set_default_value('Лето, которое он запомнит навсегда') ->set_width(50) ->set_help_text('Основной заголовок страницы. Эмоциональный, зацепляющий.'), Field::make('text', 'hero_title_span', 'Заголовок (вторая часть, цветная)') ->set_default_value('Big Summer Fun!') ->set_width(50) ->set_help_text('Выделяется цветом на фоне основного.'), Field::make('separator', 'hero_cta_sep', 'Кнопка'), Field::make('text', 'hero_btn_primary', 'Текст главной кнопки (CTA)') ->set_default_value('Записаться на пробный день') ->set_width(100) ->set_help_text('Главное действие, к которому призываем. Лучше: конкретная выгода, а не действие.'), Field::make('separator', 'hero_metrics_sep', 'Метрики доверия (блок достижений)'), Field::make('image', 'hero_metric_1_img', 'Иконка метрики 1 (изображение)') ->set_width(30) ->set_help_text('Оптимально: 1200x800px, WebP/JPG'), Field::make('text', 'hero_metric_1_number', 'Число метрики 1') ->set_default_value('90+') ->set_width(30), Field::make('text', 'hero_metric_1_label', 'Подпись метрики 1') ->set_default_value('Количество клубов') ->set_width(40), Field::make('image', 'hero_metric_2_img', 'Иконка метрики 2 (изображение)') ->set_width(30) ->set_help_text('Оптимально: 1200x800px, WebP/JPG'), Field::make('text', 'hero_metric_2_number', 'Число метрики 2') ->set_default_value('570K+') ->set_width(30), Field::make('text', 'hero_metric_2_label', 'Подпись метрики 2') ->set_default_value('Юных инноваторов') ->set_width(40), Field::make('image', 'hero_metric_3_img', 'Иконка метрики 3 (изображение)') ->set_width(30) ->set_help_text('Оптимально: 1200x800px, WebP/JPG'), Field::make('text', 'hero_metric_3_number', 'Число метрики 3') ->set_default_value('49K+') ->set_width(30), Field::make('text', 'hero_metric_3_label', 'Подпись метрики 3') ->set_default_value('Стипендий') ->set_width(40), )) ->add_tab('ℹ️ О нас', array( Field::make('html', 'about_tab_desc', '') ->set_html('

Секция: .about-us

'), Field::make('separator', 'about_us_sep', 'Текст и фото'), Field::make('image', 'about_us_img', 'Фото') ->set_help_text('Оптимально: 1200x800px, WebP/JPG. Реальные дети, эмоции.') ->set_width(30), Field::make('textarea', 'about_us_text', 'Текст о нас') ->set_help_text('Краткий текст о лагере. Выводится на странице лагеря после Hero-секции.') ->set_default_value('Dekart — это сеть детских клубов, где наука, творчество и спорт объединяются в одну захватывающую программу. Мы помогаем детям раскрывать таланты, находить друзей и проводить лето с пользой. Наши вожатые — профессиональные педагоги и наставники, которые создают атмосферу доверия и вдохновения. Каждый день в лагере — это новое открытие.'), )) ->add_tab('🏭 Преимущества', array( Field::make('html', 'suggestions_tab_desc', '') ->set_html('

Секция: .suggestions

'), Field::make('complex', 'suggestions', 'Блок «Почему выбирают нас»') ->set_layout('tabbed-horizontal') ->set_help_text('3–6 преимуществ с заголовком и описанием.') ->add_fields(array( Field::make('text', 'suggestions_title', 'Заголовок') ->set_width(100), Field::make('textarea', 'suggestions_text', 'Описание') ->set_width(100), )), )) ->add_tab('📅 Программы', array( Field::make('html', 'programs_tab_desc', '') ->set_html('

Секция: .programs

'), Field::make('complex', 'programs', 'Список программ (смен)') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте каждую тематическую смену отдельной записью.') ->add_fields(array( Field::make('image', 'programs_img', 'Изображение смены') ->set_help_text('Оптимально: 1200x800px, WebP/JPG') ->set_width(100), Field::make('text', 'programs_title', 'Название смены') ->set_width(50) ->set_help_text('Например: «Космический десант»'), Field::make('text', 'programs_date', 'Даты проведения') ->set_width(50) ->set_help_text('Например: «2–6 июня»'), Field::make('textarea', 'programs_text', 'Краткое описание (в карточке)') ->set_width(100) ->set_help_text('2–3 предложения.'), Field::make('text', 'programs_price', 'Стоимость (в рублях)') ->set_attribute('type', 'number') ->set_width(50), Field::make('text', 'programs_days', 'Количество дней') ->set_width(50) ->set_help_text('Например: «5 дней» или «7 дней»'), Field::make('rich_text', 'programs_content', 'Полное описание (в модальном окне)') ->set_width(100) ->set_help_text('Полный текст программы для всплывающего окна.'), )), )) ->add_tab('💰 Цены', array( Field::make('html', 'pricing_tab_desc', '') ->set_html('

Секция: .bring-child

'), Field::make('text', 'price_half_day', 'Стоимость за половину дня (в рублях)') ->set_attribute('type', 'number') ->set_width(50) ->set_help_text('Цена за 5 дней, например: 12900'), Field::make('text', 'price_full_day', 'Стоимость за полный день (в рублях)') ->set_attribute('type', 'number') ->set_width(50) ->set_help_text('Цена за 5 дней, например: 17900'), )) ->add_tab('👨‍🏫 Наставники', array( Field::make('html', 'mentors_tab_desc', '') ->set_html('

Секция: .mentors

'), Field::make('complex', 'mentors', 'Список наставников лагеря') ->set_layout('tabbed-horizontal') ->set_help_text('Каждый наставник — отдельная запись.') ->add_fields(array( Field::make('text', 'mentor_name', 'ФИО наставника') ->set_width(50), Field::make('image', 'mentor_foto', 'Фото наставника') ->set_help_text('Оптимально: 1200x800px, WebP/JPG') ->set_width(50), Field::make('text', 'mentor_job', 'Должность в лагере') ->set_width(100), Field::make('textarea', 'mentor_about', 'О себе') ->set_help_text('Кратко о наставнике (показывается на карточке).'), )) )) ->add_tab('⏰ Распорядок дня', array( Field::make('html', 'routine_tab_desc', '') ->set_html('

Секция: .routine

'), Field::make('complex', 'routine', 'Расписание по времени') ->set_help_text('Добавьте пункты распорядка по порядку следования.') ->add_fields(array( Field::make('text', 'routine_time', 'Время') ->set_width(15) ->set_help_text('Формат: 08:30'), Field::make('text', 'routine_title', 'Название активности') ->set_width(40) ->set_help_text('Например: «Научный блок»'), Field::make('textarea', 'routine_text', 'Описание') ->set_width(45), )) )) ->add_tab('📷 Фотографии', array( Field::make('html', 'fotos_tab_desc', '') ->set_html('

Секция: .foto

'), Field::make('complex', 'fotos', 'Галерея фотографий') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте реальные фото детей из лагеря. Формат: WebP, 1:1 или 4:3.') ->add_fields(array( Field::make('image', 'foto', 'Фотография') ->set_help_text('Оптимально: 1200x800px, WebP/JPG, до 300Кб'), )), )) ->add_tab('❓ Вопросы и ответы (FAQ)', array( Field::make('html', 'faq_tab_desc', '') ->set_html('

Секция: .camp-faq

'), Field::make('complex', 'questions', 'Список вопросов и ответов') ->set_layout('tabbed-horizontal') ->set_help_text('Чем больше вопросов, тем меньше возражений у родителей. Минимум 7–8 вопросов.') ->add_fields(array( Field::make('textarea', 'questions_question', 'Текст вопроса') ->set_width(30), Field::make('textarea', 'questions_answer', 'Текст ответа') ->set_width(70), )), )) ->add_tab('⭐ Отзывы', array( Field::make('html', 'reviews_tab_desc', '') ->set_html('

Секция: .camp-reviews. Отзывы выводятся на странице лагеря.

'), Field::make('complex', 'camp_reviews_list', 'Отзывы о лагере') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте отзывы родителей. Показываются на странице лагеря.') ->add_fields(array( Field::make('image', 'review_avatar', 'Аватар') ->set_width(15) ->set_help_text('Опционально. Если не указано — генерируется из имени.'), Field::make('text', 'review_author', 'Имя автора') ->set_width(25), Field::make('text', 'review_rating', 'Оценка (1–5)') ->set_width(10) ->set_attribute('type', 'number'), Field::make('date', 'review_date', 'Дата отзыва') ->set_width(15) ->set_storage_format('d.m.Y') ->set_input_format('d.m.Y', 'd.m.Y') ->set_picker_options(array( 'altInput' => false )) ->set_help_text('Для Schema.org Review.datePublished. Формат: ДД.ММ.ГГГГ'), Field::make('association', 'review_teacher', 'Преподаватель') ->set_width(25) ->set_types(array( array( 'type' => 'post', 'post_type' => 'teacher', ), )) ->set_max(1) ->set_help_text('Если родитель хвалит конкретного учителя — привяжите отзыв к нему. Необязательно.'), Field::make('textarea', 'review_text', 'Текст отзыва') ->set_width(35), )), )) ->add_tab('📍 Контакты и карта', array( Field::make('html', 'contacts_tab_desc', '') ->set_html('

⚠️ Данные филиала (телефон, email, адрес, соцсети) — в Настройки филиала (меню слева). Здесь только подпись метки карты.

'), Field::make('text', 'contact_location_text', 'Подпись метки на карте') ->set_width(50) ->set_help_text('Что написано в баллуне на карте.'), )) ->add_tab('🗂️ Битрикс24', array( Field::make('html', 'bitrix_tab_desc', '') ->set_html('

Секция: .modal-camp-request-form
Скрипт кнопок перенесён в Настройки филиала → 🎯 СКРИПТ ДЛЯ КНОПОК → для лагеря.

'), )); // ════════════════════════════════════════════════════════════ // СТРАНИЦА ОТЗЫВОВ (page-reviews.php) // ════════════════════════════════════════════════════════════ Container::make('post_meta', '⭐ Настройки страницы Отзывы') ->where('post_template', '=', 'page-reviews.php') ->add_tab('🧑‍🏫 Hero (первый экран)', array( Field::make('html', 'reviews_hero_tab_desc', '') ->set_html('

H1 формируется автоматически из города. Подзаголовок, метрики и CTA настраиваются ниже.

'), Field::make('text', 'reviews_hero_subtitle', 'Подзаголовок (под H1)') ->set_default_value('Родители доверяют нам самое главное — вот что они говорят о нас') ->set_width(100) ->set_help_text('Текст под заголовком H1. Отображается белым на тёмном фоне hero.'), Field::make('separator', 'reviews_metric_sep', 'Метрики доверия'), Field::make('text', 'reviews_hero_metric_1_number', 'Метрика 1 — число') ->set_default_value('500+') ->set_width(30) ->set_help_text('Крупная цифра, которая сразу привлекает внимание. Выбирайте самую сильную — ту, что впечатляет больше всего: количество учеников, лет на рынке, % поступления. Добавьте + или % для эффекта. Примеры: «500+», «98%», «15».'), Field::make('text', 'reviews_hero_metric_1_label', 'Метрика 1 — подпись') ->set_default_value('счастливых семей') ->set_width(70) ->set_help_text('Подпись к цифре из левого поля. Объясняет, что именно посчитано. Совет: используйте родительный падеж — звучит весомее. Примеры: «счастливых семей», «выпускников», «учеников». Не пишите просто «семей» — добавьте «счастливых», это продаёт эмоцию.'), Field::make('text', 'reviews_hero_metric_2_number', 'Метрика 2 — число') ->set_default_value('12+') ->set_width(30) ->set_help_text('Вторая по силе цифра. Не ставьте 0, 1, 2 — они не впечатляют. Примеры: «12+», «97%», «50».'), Field::make('text', 'reviews_hero_metric_2_label', 'Метрика 2 — подпись') ->set_default_value('лет в образовании') ->set_width(70) ->set_help_text('Подпись к цифре 2. Примеры: «лет на рынке», «лет в образовании», «преподавателей». Старайтесь, чтобы подпись читалась вместе с цифрой как законченная фраза: «12+ лет в образовании».'), Field::make('text', 'reviews_hero_metric_3_number', 'Метрика 3 — число') ->set_default_value('4.9') ->set_width(30) ->set_help_text('Третья цифра. Если сильных цифр больше нет — поставьте рейтинг или оценку. Примеры: «4.9», «5.0», «топ-3». Дробные числа пишите через точку.'), Field::make('text', 'reviews_hero_metric_3_label', 'Метрика 3 — подпись') ->set_default_value('рейтинг на Яндексе') ->set_width(70) ->set_help_text('Подпись к цифре 3. Примеры: «рейтинг на Яндексе», «звёзд», «место в рейтинге области». Если указали рейтинг — обязательно добавьте «из 5» или площадку: «рейтинг на Яндексе» звучит убедительнее, чем просто «рейтинг».'), Field::make('text', 'reviews_hero_metric_4_number', 'Метрика 4 — число') ->set_default_value('14') ->set_width(30) ->set_help_text('Четвёртая цифра. Например: количество отзывов, количество педагогов, лет опыта.'), Field::make('text', 'reviews_hero_metric_4_label', 'Метрика 4 — подпись') ->set_default_value('отзывов о школе') ->set_width(70) ->set_help_text('Подпись к цифре 4. Пример: «отзывов о школе», «педагогов», «лет на рынке».'), Field::make('separator', 'reviews_hero_badges_sep', '🏷️ Плавающие подписи (у фото)'), Field::make('complex', 'reviews_hero_badges', 'Подписи-плашки вокруг фото') ->set_layout('tabbed-horizontal') ->set_help_text('До 4 подписей, которые отображаются вокруг фото в hero-секции. Каждая запись: иконка (emoji) + текст. Позиции фиксированы: 1 = верх-право, 2 = лево-середина, 3 = низ-право, 4 = лево-верх. Если записей меньше 4 — отсутствующие не выводятся.') ->add_fields(array( Field::make('text', 'badge_icon', 'Иконка (emoji)') ->set_width(20) ->set_help_text('Один символ emoji для плашки. Примеры: ⭐ 🎓 ❤️ 🌟 🎮 📚 👩‍🏫 🏆'), Field::make('textarea', 'badge_text', 'Текст подписи') ->set_width(80) ->set_help_text('Короткий текст плашки. Можно использовать HTML: <strong>, <br>. Примеры: «Рейтинг 4.9 на Яндексе», «500+ выпускников», «Родители рекомендуют», «Школа <strong>№1</strong> в районе».'), )), // CTA кнопка — статическая в шаблоне, открывает модалку Bitrix24 )) ->add_tab('📝 Вступление (SEO-текст)', array( Field::make('html', 'reviews_intro_tab_desc', '') ->set_html('

Секция: .reviews-intro — SEO-текст в начале страницы. Управляется из админки, чтобы можно было править текст без редактирования шаблона.

'), Field::make('text', 'reviews_intro_price_text', 'Стоимость обучения (текст)') ->set_default_value('от 40 000 ₽ в месяц') ->set_width(50) ->set_help_text('Текст стоимости в блоке .reviews-intro__info. Пример: «от 40 000 ₽ в месяц» или «от 35 000 ₽/мес». Если поле пусто — строка не выводится.'), Field::make('text', 'reviews_intro_hours', 'Режим работы (текст)') ->set_default_value('ежедневно с 8:00 до 19:00, кроме воскресенья') ->set_width(50) ->set_help_text('Текст режима работы в блоке .reviews-intro__info. Отображается на странице отзывов под SEO-текстом. Пример: «ежедневно с 8:00 до 19:00, кроме воскресенья» или «Пн–Пт: 08:00–19:00, Сб: 09:00–14:00». Если пусто — строка не выводится.'), Field::make('textarea', 'reviews_intro_lead', 'Лид-абзац (первый, крупный)') ->set_default_value('Частная школа Декарт в Щёлково — это образовательное пространство, где каждый ребёнок получает внимание, заботу и качественные знания. Мы работаем в Щёлковском городском округе с 2010 года и за это время помогли раскрыть потенциал сотням учеников. Отзывы родителей о школе Декарт — это реальные истории семей, которые доверили нам образование своих детей. Мы публикуем их, чтобы вы могли принять взвешенное решение.') ->set_help_text('Первый, самый заметный абзац. Отображается крупнее остальных, отделён линией. 150–180 символов — оптимально. Должен вовлекать и отвечать на главный вопрос посетителя.'), Field::make('textarea', 'reviews_intro_card_1', 'Блок «О школе» (карточка 1)') ->set_default_value('В нашей частной школе в Щёлково учатся дети с 1 по 11 класс. Мы предлагаем программы начального общего образования, подготовки к ОГЭ и ЕГЭ, углублённое изучение английского языка. Классы небольшие — до 12 человек, поэтому каждый ученик получает индивидуальный подход. Родители, которые ищут качественное образование в Щёлково и Московской области, выбирают Декарт за профессионализм педагогов и тёплую атмосферу.') ->set_help_text('Левая карточка в сетке из двух колонок. Здесь — факты о школе: классы, программы, преимущества. 100–200 символов.'), Field::make('textarea', 'reviews_intro_card_2', 'Блок «О странице» (карточка 2)') ->set_default_value('Мы ценим каждое мнение и постоянно работаем над улучшением обучения. Ниже вы найдёте реальные отзывы родителей о нашей частной школе, достижения учеников и ответы на частые вопросы. Приятного чтения!') ->set_help_text('Правая карточка в сетке. Объясняет, что пользователь найдёт на странице. 80–120 символов.'), )) ->add_tab('🏠 Почему выбирают (локальный)', array( Field::make('html', 'reviews_local_tab_desc', '') ->set_html('

Секция: .reviews-local — список причин выбрать школу с привязкой к городу. Заголовок секции статический в шаблоне, подставляет город из настроек филиала.

'), Field::make('complex', 'reviews_local_items', 'Причины') ->set_layout('tabbed-horizontal') ->set_help_text('4–6 причин, почему родители выбирают именно Декарт. Каждая — жирный заголовок + описание. Текст должен быть с гео-привязкой (упоминания города, района, местных реалий).') ->add_fields(array( Field::make('text', 'title', 'Заголовок') ->set_width(30) ->set_help_text('Короткий, ёмкий заголовок. 2–5 слов. ✅ «Удобное расположение» ❌ «Мы находимся в удобном месте с хорошей транспортной доступностью».'), Field::make('textarea', 'text', 'Описание') ->set_width(70) ->set_help_text('2–3 предложения с гео-привязкой. Упомяните город, район, местные реалии. Родитель должен почувствовать: «Это про мой город, это для меня».'), )), )) ->add_tab('📊 Наши результаты (цифрами)', array( Field::make('html', 'reviews_results_tab_desc', '') ->set_html('

Секция: .results

'), Field::make('text', 'reviews_results_title', 'Заголовок секции') ->set_default_value('Декарт в цифрах') ->set_width(100) ->set_help_text('Заголовок блока с результатами. Должен привлекать внимание и обещать пользу. Примеры: «Декарт в цифрах», «Наши достижения», «Почему нам доверяют родители». Избегайте канцеляризмов: «Статистические показатели» — плохо.'), Field::make('complex', 'reviews_results', 'Показатели') ->set_layout('tabbed-horizontal') ->set_help_text('4-6 цифр, которые доказывают качество школы. Каждый показатель должен отвечать на вопрос родителя: «Почему мы должны вам доверять?». Примеры: % поступивших в вузы, средний балл учеников, стаж преподавателей, количество учеников. Избегайте абстрактных цифр вроде «более 50 довольных клиентов» — звучит неубедительно.') ->add_fields(array( Field::make('text', 'number', 'Число') ->set_width(25) ->set_help_text('Сама цифра — должна выглядеть эффектно и убедительно. ✅ «100%», «85%», «500+», «50». ❌ «много», «больше 10», «каждый второй» — размытые формулировки не работают. Используйте % и + чтобы цифра казалась больше.'), Field::make('select', 'icon', 'Иконка') ->set_width(20) ->set_help_text('Иконка рядом с цифрой. Подбирайте по смыслу: 🏆 достижения, 📖 учёба, 👥 ученики, ❤️ любовь/забота. Иконка помогает быстро понять суть.') ->add_options(array( 'ph-graduation-cap' => '🎓 Диплом / шапочка', 'ph-chats' => '💬 Речевой пузырь', 'ph-users-three' => '👥 Люди / группа', 'ph-star' => '⭐ Звезда', 'ph-shield-check' => '🛡️ Галочка / щит', 'ph-book' => '📖 Книга', 'ph-heart' => '❤️ Сердце', 'ph-clock' => '🕐 Часы', 'ph-house' => '🏠 Дом', 'ph-trophy' => '🏆 Кубок', )), Field::make('text', 'label', 'Подпись') ->set_width(55) ->set_help_text('Пояснение к цифре. Текст должен быть понятен САМ ПО СЕБЕ, даже без цифры. ✅ «учеников сдают ВПР на 4 и 5», ❌ «сдают ВПР» (что? кто?). Длина — 3-5 слов. Примеры: «лет на рынке», «выпускников поступают в топ-вузы», «средний балл учеников по математике».'), )), )) ->add_tab('❓ FAQ (вопросы-ответы)', array( Field::make('html', 'reviews_faq_tab_desc', '') ->set_html('

🎯 Какие вопросы добавлять на эту страницу

Эта страница — последний шаг перед записью. Человек уже почти решился, он читает отзывы чтобы окончательно убедиться. Вопросы и ответы здесь должны снимать последние сомнения, а не рассказывать о центре в целом.

✅ Правильные вопросы — про доверие и финальные сомнения:

❌ Неправильные вопросы — их размещайте на других страницах:

📐 Сколько вопросов добавлять:

Оптимально 4–6. Меньше — не закрывает сомнения, больше — отвлекает от записи.

'), // Заголовок секции — статический в шаблоне Field::make('complex', 'reviews_faq', 'Вопросы и ответы') ->set_layout('tabbed-horizontal') ->set_help_text('Вопросы — снимают последние сомнения перед записью. 4–6 штук.') ->add_fields(array( Field::make('textarea', 'question', 'Вопрос') ->set_width(30) ->set_help_text('Вопрос должен звучать так, как его задаст реальный родитель — простыми словами, без канцелярита. ✅ «А если ребёнок не захочет ходить?» ❌ «Как преодолеть сопротивление ребёнка к посещению занятий?». Первое — вызывает доверие, второе — выглядит как копипаста с другого сайта.'), Field::make('textarea', 'answer', 'Ответ') ->set_width(70) ->set_help_text('Ответ должен снимать страх или сомнение, а не просто сухо информировать. Используйте слова-усилители: «да», «конечно», «бесплатно», «попробуйте», «всегда можно». Структура: 1) Поймите чувства родителя («Это нормально, что вы переживаете…»). 2) Дайте решение («…поэтому у нас есть пробный урок»). 3) Позовите к действию («Приходите познакомиться — это бесплатно»).'), )), )) ->add_tab('⭐ Отзывы (карточки)', array( Field::make('html', 'reviews_cards_tab_desc', '') ->set_html('

Секция: .reviews-grid. Карточки отзывов, которые видят посетители.

'), Field::make('complex', 'reviews_cards', 'Отзывы') ->set_layout('tabbed-horizontal') ->set_help_text('Карточки отзывов родителей — главный элемент доверия на странице. Лучше 3-4 подробных отзыва, чем 10 коротких «всё нравится». Хороший отзыв содержит: с чего начали → что изменилось → какой результат. Эмоциональные отзывы продают лучше фактов.') ->add_fields(array( Field::make('text', 'review_author', 'Имя автора') ->set_width(22) ->set_help_text('Реальное имя родителя: «Анна», «Сергей», «Екатерина М.». Имена повышают доверие. Можно добавить статус: «Анна, мама Артёма». НЕ используйте анонимные «Родитель» или «Гость» — это вызывает подозрение.'), Field::make('image', 'review_photo', 'Фото автора') ->set_width(13) ->set_value_type('url') ->set_help_text('Фото родителя (реальное лицо). Если не загружено — показывается аватар-заглушка с первой буквой имени. Фото повышает доверие к отзыву. Рекомендуемый размер: 96×96px, формат: WebP/JPG.'), Field::make('text', 'review_rating', 'Оценка (1–5)') ->set_width(10) ->set_attribute('type', 'number') ->set_help_text('Оценка от 1 до 5. Ставьте 5 — если отзыв восторженный. 4 — если есть мелкие замечания (это добавляет правдоподобности). Оценки 3 и ниже публиковать не стоит — они снижают доверие.'), Field::make('date', 'review_date', 'Дата отзыва') ->set_storage_format('d.m.Y') ->set_input_format('d.m.Y', 'd.m.Y') ->set_picker_options(array( 'altInput' => false, )) ->set_help_text('Дата отзыва. Свежие отзывы (2024-2025) работают лучше старых. Формат: ДД.ММ.ГГГГ (например: 10.03.2025). Можно открыть календарь — иконка справа.') ->set_width(20), Field::make('association', 'review_teacher', 'Преподаватель') ->set_width(30) ->set_max(1) ->set_types(array( array( 'type' => 'post', 'post_type' => 'teacher', ), )) ->set_help_text('Если родитель хвалит конкретного учителя — привяжите отзыв к нему. Тогда на странице преподавателя тоже появится этот отзыв. Необязательно.'), Field::make('textarea', 'review_text', 'Текст отзыва') ->set_width(35) ->set_help_text('Полный текст отзыва. 3-5 предложений — оптимально. Хорошая структура: 1) С чего начали («Пришли с проблемой…»), 2) Что изменилось («Через месяц ребёнок…»), 3) Результат («Сейчас читает лучше всех в классе»). Эмоции и конкретные детали убеждают сильнее общих фраз. Орфографию можно поправить, но сохраните живую речь.'), )), )) // 📝 Форма отзыва — тексты статические в шаблоне page-reviews.php // 🎯 Финальный CTA — статический в шаблоне page-reviews.php. // Скрипт для кнопок — branch_button_script (Settings API → Настройки филиала). ->add_tab('🔗 Перелинковка', array( Field::make('html', 'reviews_cross_tab_desc', '') ->set_html('

Секция: .cross-links — ссылки на другие разделы сайта. Улучшает навигацию и SEO.

'), Field::make('text', 'reviews_cross_title', 'Заголовок') ->set_default_value('Наши программы') ->set_width(100) ->set_help_text('Заголовок блока со ссылками. По умолчанию «Наши программы». Альтернативы: «Узнайте больше», «Другие направления», «Выберите программу». Важно: заголовок должен подталкивать перейти по ссылкам.'), Field::make('complex', 'reviews_cross_links', 'Ссылки на другие страницы') ->set_layout('tabbed-horizontal') ->set_help_text('5-7 ссылок на другие страницы сайта. Это помогает родителям найти нужную программу и улучшает SEO (перелинковка). Обязательно добавьте: подготовка к школе, начальная школа, средняя школа, ВПР, ОГЭ/ЕГЭ, продлёнка, летний лагерь.') ->add_fields(array( Field::make('text', 'title', 'Название') ->set_width(50) ->set_help_text('Текст ссылки, который увидит посетитель. ✅ «Подготовка к школе», «Группа продлённого дня». Название должно быть понятно без контекста.'), Field::make('text', 'url', 'Ссылка') ->set_width(50) ->set_help_text('URL страницы. Можно указать сокращённо: /podgotovka-k-shkole/ или полный адрес. Скопируйте из адресной строки браузера при просмотре нужной страницы.'), )), )) ->add_tab('💎 Видеоотзывы', array( Field::make('html', 'reviews_video_tab_desc', '') ->set_html('

Секция: .video-reviews. Видеоотзывы — самый убедительный формат контента. Добавьте 2-4 коротких видео (1-3 минуты).

'), Field::make('text', 'reviews_video_title', 'Заголовок секции') ->set_default_value('Видеоотзывы родителей') ->set_width(100) ->set_help_text('Заголовок секции с видео. По умолчанию «Видеоотзывы родителей». Можно изменить на «Смотрите, что говорят родители», «Истории наших семей» — более эмоциональные варианты работают лучше.'), Field::make('complex', 'reviews_video', 'Видеоотзывы') ->set_layout('tabbed-horizontal') ->set_help_text('Добавьте видеоотзывы — это повышает доверие сильнее, чем текст. Видео должны быть на YouTube, в открытом доступе, длительностью 1-3 минуты. Хорошо, если родитель рассказывает историю: пришли с проблемой → как школа помогла → результат.') ->add_fields(array( Field::make('text', 'name', 'Имя автора') ->set_width(30) ->set_help_text('Имя родителя из видео. Например: «Мария, мама Артёма». Если в видео несколько человек — укажите главного героя.'), Field::make('oembed', 'url', 'Ссылка на видео (YouTube)') ->set_width(70) ->set_help_text('Ссылка на видео. Поддерживаются: YouTube (https://www.youtube.com/watch?v=...), VK Видео (https://vk.com/video-... или https://vkvideo.ru/...), Rutube и другие oEmbed-провайдеры. Видео должно быть в открытом доступе. Проверьте ссылку перед публикацией.'), )), )) ->add_tab('📸 Фото с занятий', array( Field::make('html', 'reviews_photos_tab_desc', '') ->set_html('

Секция: .reviews-photos — фотогалерея с занятий. 4-8 фото повышают доверие и показывают атмосферу школы. Рекомендуемый размер: 800×600px, формат WebP.

'), Field::make('text', 'reviews_photos_title', 'Заголовок секции') ->set_default_value('Фото с занятий') ->set_width(100) ->set_help_text('Заголовок галереи. По умолчанию «Фото с занятий». Альтернативы: «Как проходят занятия», «Наши будни», «Атмосфера школы».'), Field::make('media_gallery', 'reviews_photos', 'Фотографии') ->set_type(array( 'image' )) ->set_help_text('Загрузите 4-8 фотографий. РЕКОМЕНДУЕМЫЙ РАЗМЕР: 800×600px (4:3), формат WebP. Все фото в галерее автоматически обрезаются до одинакового размера на странице (4:3), соотношение сторон сохраняется.'), )); } // функция получения id курса по его названию function get_post_by_title($page_title) { $query = new WP_Query( [ 'post_type' => 'course', 'title' => $page_title, 'post_status' => 'publish', 'posts_per_page' => 1, 'update_post_term_cache' => false, 'update_post_meta_cache' => false, 'orderby' => 'post_date ID', 'order' => 'ASC', 'no_found_rows' => true, 'ignore_sticky_posts' => true, ] ); wp_reset_postdata(); if ($query->post) { return $query->post->ID; } else { return null; } } // функция случайного цвета function rand_color() { return sprintf('#%06X', mt_rand(0, 0xFFFFFF)); } add_theme_support('post-thumbnails'); add_action('pre_get_posts', 'exclude_custom_taxonomy_posts'); function exclude_custom_taxonomy_posts($query) { if (!is_admin() && $query->is_main_query() && ($query->is_tax('trainingCategory') || $query->is_tax('direction'))) { $query->set_404(); } } function add_og_image() { $term = get_queried_object(); if (! is_a($term, 'WP_Term') || empty($term->term_id)) { return; } $snippet = carbon_get_term_meta($term->term_id, 'snippet'); if ($snippet) { echo '' . "\n"; } } add_action('wp_head', 'add_og_image'); function yoastVariableToTitle($post_id) { $yoast_title = get_post_meta($post_id, '_yoast_wpseo_title', true); $title = strstr($yoast_title, '%%', true); if (empty($title)) { $title = get_the_title($post_id); } $wpseo_titles = get_option('wpseo_titles'); $sep_options = WPSEO_Option_Titles::get_instance()->get_separator_options(); if (isset($wpseo_titles['separator']) && isset($sep_options[$wpseo_titles['separator']])) { $sep = $sep_options[$wpseo_titles['separator']]; } else { $sep = '-'; } $site_title = get_bloginfo('name'); $meta_title = $title . ' ' . $sep . ' ' . $site_title; return $meta_title; } function replaceQuotes($text) { $text = str_replace(['"'], "'", $text); return $text; } /** * Санитация для поля branch_button_script. * Сохраняет \n"; $gtm_head_default = "\n\n"; $gtm_body_default = "\n\n"; $footer_default = "\n\n"; if (get_option('dekart_counter_yandex') === false) { add_option('dekart_counter_yandex', $yandex_default); } if (get_option('dekart_counter_gtm_head') === false) { add_option('dekart_counter_gtm_head', $gtm_head_default); } if (get_option('dekart_counter_gtm_body') === false) { add_option('dekart_counter_gtm_body', $gtm_body_default); } if (get_option('dekart_counter_footer') === false) { add_option('dekart_counter_footer', $footer_default); } } function dekart_counters_page() { ?>

Счетчики

Яндекс.Метрика / Tag Manager

Yandex Code

Код счетчика. Выводится в <head>.

Google Tag Manager (GTM)

GTM Head

Основной код GTM. Выводится в <head>.

GTM Body

Код <noscript>. Выводится сразу после открытия <body> через хук wp_body_open.

Произвольные скрипты

Site-wide Footer Scripts

Для чатов, пикселей и прочих скриптов. Выводится в <footer>.

id, 'carbon_fields') !== false; $is_branch = strpos($screen->id, 'branch-settings') !== false; if (! $is_carbon && ! $is_branch) { return; } ?> 'text', 'branch_city' => 'text', 'branch_region' => 'text', 'branch_address' => 'text', 'branch_coords' => 'text', 'branch_postal_code' => 'text', 'branch_phone' => 'text', 'branch_email' => 'email', 'branch_name' => 'text', 'branch_price_range' => 'text', 'branch_logistics_walk' => 'text', 'branch_logistics_parking' => 'text', 'branch_logistics_schools' => 'text', 'branch_area_served' => 'text', 'branch_director_name' => 'text', 'branch_director_creds' => 'text', ); foreach ($text_fields as $slug => $type) { register_setting('dekart_branch_group', $slug, array( 'sanitize_callback' => $type === 'email' ? 'sanitize_email' : ( $type === 'url' ? 'esc_url_raw' : 'sanitize_text_field' ) )); } register_setting('dekart_branch_group', 'branch_logo', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_social'); register_setting('dekart_branch_group', 'branch_messengers'); register_setting('dekart_branch_group', 'branch_button_script', array( 'sanitize_callback' => 'dekart_sanitize_script_field' )); register_setting('dekart_branch_group', 'branch_camp_script', array( 'sanitize_callback' => 'dekart_sanitize_script_field' )); register_setting('dekart_branch_group', 'branch_myreviews_widget', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_ext_yandex', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_ext_google', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_ext_2gis', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_ext_otzovik', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_ext_vk', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_ext_other_name', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_ext_other_url', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_og_site_name', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_ext_review_count', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_avg_rating', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_rating_yandex', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_rating_2gis', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_rating_vk', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_rating_otzovik', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_remaining_seats', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_messenger_whatsapp', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_messenger_telegram', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_messenger_max', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_messenger_whatsapp_on', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_messenger_telegram_on', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_messenger_max_on', array( 'sanitize_callback' => 'absint' )); register_setting('dekart_branch_group', 'branch_messenger_extra'); register_setting('dekart_branch_group', 'branch_schema_description', array( 'sanitize_callback' => 'sanitize_textarea_field' )); register_setting('dekart_branch_group', 'branch_area_served', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_school', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_preschool', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_afterschool', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_exam', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_camp', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_price_clubs', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_work_hours', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_hours', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_google_place_id', array( 'sanitize_callback' => 'sanitize_text_field' )); register_setting('dekart_branch_group', 'branch_google_maps_url', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_google_business_url', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_yandex_business_url', array( 'sanitize_callback' => 'esc_url_raw' )); register_setting('dekart_branch_group', 'branch_logistics_walk', array( 'sanitize_callback' => 'sanitize_textarea_field' )); register_setting('dekart_branch_group', 'branch_logistics_parking', array( 'sanitize_callback' => 'sanitize_textarea_field' )); register_setting('dekart_branch_group', 'branch_logistics_nearby', array( 'sanitize_callback' => 'sanitize_textarea_field' )); // Поля branch_map_url, branch_founded, branch_photos — удалены. // Они дублировали CF таб «SEO и микроразметка» (schema_*). // Чтение: inc/schema.php → dekart_schema_option() → CF → Settings API (backward compat). } function dekart_branch_settings_page() { ?>

Настройки филиала

🗄️ Сброс кеша

Полная диагностика и очистка: проверка файлов, установка drop-in, сброс кеша и транзиентов.

'teacher', 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'title', 'order' => 'ASC', )); foreach ($teachers as $t) { $options[ $t->ID ] = esc_html($t->post_title); } return $options; } // ───────────────────────────────────────────────────────────── // ACF: Отзывы (Лагерь) — группа полей // ───────────────────────────────────────────────────────────── // ───────────────────────────────────────────────────────────── // 🗄️ AJAX: Сброс кеша (кнопка в Настройки филиала) // ───────────────────────────────────────────────────────────── add_action('wp_ajax_dekart_flush_cache', 'dekart_ajax_flush_cache'); function dekart_ajax_flush_cache() { check_ajax_referer('dekart_flush_cache_nonce', 'nonce'); if (! current_user_can('manage_options')) { wp_send_json_error(array( 'message' => 'Нет прав' )); } $log = array(); $errors = 0; $abspath = defined('ABSPATH') ? ABSPATH : dirname(__DIR__, 4) . '/'; // ── 1. Проверка файлов ── $files = array( 'MU-плагин (object-cache-bootstrap)' => WP_CONTENT_DIR . '/mu-plugins/object-cache-bootstrap.php', 'Плагин Memcached (object-cache.php)' => WP_CONTENT_DIR . '/plugins/memcached/object-cache.php', 'Тема (functions.php)' => get_template_directory() . '/functions.php', 'wp-config.php' => $abspath . 'wp-config.php', ); $log[] = array( 'type' => 'info', 'text' => '🔍 Проверка файлов системы:' ); foreach ($files as $label => $path) { if (file_exists($path)) { $size = size_format(filesize($path)); $log[] = array( 'type' => 'ok', 'text' => "{$label} — найден ({$size})" ); } else { $log[] = array( 'type' => 'warn', 'text' => "{$label} — отсутствует" ); } } // ── 2. PHP extension Memcache ── $log[] = array( 'type' => 'info', 'text' => '🔍 Проверка PHP-расширения:' ); if (class_exists('Memcache') || class_exists('Memcached')) { $ext = class_exists('Memcached') ? 'memcached' : 'memcache'; $log[] = array( 'type' => 'ok', 'text' => "PHP-расширение {$ext} — установлено" ); } else { $log[] = array( 'type' => 'warn', 'text' => 'PHP-расширение memcache/memcached — не найдено (обратитесь в хостинг)' ); } // ── 3. Memcached drop-in ── $source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php'; $target = WP_CONTENT_DIR . '/object-cache.php'; $log[] = array( 'type' => 'info', 'text' => '🔍 Проверка drop-in Memcached:' ); if (file_exists($target)) { $size = size_format(filesize($target)); $log[] = array( 'type' => 'ok', 'text' => "Drop-in уже установлен: wp-content/object-cache.php ({$size})" ); } else { if (file_exists($source)) { $copied = copy($source, $target); if ($copied) { $size = size_format(filesize($target)); $log[] = array( 'type' => 'ok', 'text' => "Drop-in скопирован: plugins/memcached/object-cache.php → wp-content/object-cache.php ({$size})" ); } else { $log[] = array( 'type' => 'fail', 'text' => 'Ошибка копирования! Проверьте права на wp-content/' ); $errors++; } } else { $log[] = array( 'type' => 'warn', 'text' => 'Плагин Memcached не установлен. Установите: wp plugin install memcached' ); } } // ── 4. Проверка WP_CACHE_KEY_SALT ── $log[] = array( 'type' => 'info', 'text' => '🔍 Проверка изоляции ключей кеша:' ); if (defined('WP_CACHE_KEY_SALT') && WP_CACHE_KEY_SALT !== '') { $log[] = array( 'type' => 'ok', 'text' => 'WP_CACHE_KEY_SALT = ' . WP_CACHE_KEY_SALT . ' (изоляция активна)' ); } else { $log[] = array( 'type' => 'fail', 'text' => 'WP_CACHE_KEY_SALT не задан! Добавьте в wp-config.php: define( "WP_CACHE_KEY_SALT", DB_NAME );' ); $errors++; } // ── 5. Versioned cache bump (MU-плагин) ── $log[] = array( 'type' => 'info', 'text' => '🔍 Инвалидация versioned cache:' ); if (function_exists('my_cache_bump_version')) { my_cache_bump_version(); $log[] = array( 'type' => 'ok', 'text' => 'Версия кеша обновлена (my_cache_bump_version)' ); } else { $log[] = array( 'type' => 'warn', 'text' => 'my_cache_bump_version() не найдена — MU-плагин не активен' ); } // ── 6. WP object cache flush ── $log[] = array( 'type' => 'info', 'text' => '🔍 Очистка объектного кеша:' ); if (function_exists('wp_cache_flush')) { wp_cache_flush(); $log[] = array( 'type' => 'ok', 'text' => 'wp_cache_flush() — выполнен (ключи ротированы)' ); } else { $log[] = array( 'type' => 'warn', 'text' => 'wp_cache_flush() — функция не найдена (drop-in не установлен)' ); } // ── 7. Transients ── $log[] = array( 'type' => 'info', 'text' => '🔍 Очистка транзиентов:' ); global $wpdb; $deleted = $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_%' OR option_name LIKE '_transient_timeout_%'"); $log[] = array( 'type' => 'ok', 'text' => "Удалено {$deleted} записей _transient_* из wp_options" ); // ── Итог ── if ($errors === 0) { $summary = array( 'type' => 'ok', 'text' => 'Всё выполнено успешно. Ошибок нет.' ); } else { $summary = array( 'type' => 'fail', 'text' => "Выполнено с {$errors} ошибкой(ами). Проверьте лог выше." ); } wp_send_json_success(array( 'log' => $log, 'summary' => $summary, )); } /** * program-pksh: разрешаем индексацию — страница содержит * официальную образовательную программу со ссылками на ФЗ №273, ФГОС ДО. * Это сильный E-E-A-T сигнал + точка входа по запросам "программа подготовка к школе фгос". * noindex был ошибочным — он убивал E-E-A-T и терял трафик по длинным образовательным запросам. */