1257 lines
37 KiB
PHP
1257 lines
37 KiB
PHP
<?php
|
||
/**
|
||
* Schema.org JSON-LD Generator — единый @graph
|
||
*
|
||
* Генерирует микроразметку для страницы «Подготовка к школе».
|
||
* Только динамические данные из Carbon Fields. Никаких хардкод-значений.
|
||
*
|
||
* @package Dekart
|
||
* @since 2026-05-31
|
||
* @see https://schema.org/Course
|
||
*/
|
||
|
||
defined( 'ABSPATH' ) || exit;
|
||
|
||
/**
|
||
* Отключаем Yoast SEO JSON-LD на странице Подготовки к школе,
|
||
* чтобы избежать дублирования WebPage + Organization.
|
||
* Аналогично page-camp.php.
|
||
*/
|
||
add_filter( 'wpseo_json_ld_output', '__return_false' );
|
||
|
||
/**
|
||
* Принудительно меняем og:type на 'website' для страницы Подготовки к школе,
|
||
* чтобы избежать несоответствия article/website в социальных сниппетах.
|
||
*/
|
||
add_filter( 'wpseo_opengraph_type', 'dekart_schema_og_type', 10, 1 );
|
||
function dekart_schema_og_type( string $type ): string {
|
||
if ( is_page_template( 'page-podgotovka-k-shkole.php' ) || is_page_template( 'page-camp.php' ) ) {
|
||
return 'website';
|
||
}
|
||
return $type;
|
||
}
|
||
|
||
/**
|
||
* Убираем article:* OG-теги для страницы Подготовки к школе,
|
||
* чтобы не было конфликта og:type=website с article:modified_time.
|
||
* Аналог page-camp.php:15-27.
|
||
*/
|
||
add_filter( 'wpseo_frontend_presenter_classes', function( array $presenters ): array {
|
||
if ( ! is_page_template( 'page-podgotovka-k-shkole.php' ) ) {
|
||
return $presenters;
|
||
}
|
||
$presenters = array_filter( $presenters, function( string $p ): bool {
|
||
return strpos( $p, 'Article_Modified_Time' ) === false
|
||
&& strpos( $p, 'Article_Published_Time' ) === false
|
||
&& strpos( $p, 'Article_Author' ) === false
|
||
&& strpos( $p, 'Article_Publisher' ) === false
|
||
&& strpos( $p, 'Label1' ) === false
|
||
&& strpos( $p, 'Data1' ) === false;
|
||
} );
|
||
return $presenters;
|
||
} );
|
||
|
||
/**
|
||
* Главная функция: сборка @graph и вывод в wp_head.
|
||
* Срабатывает только на странице с шаблоном page-podgotovka-k-shkole.php.
|
||
*/
|
||
add_action( 'wp_head', 'dekart_schema_output', 1 );
|
||
|
||
/**
|
||
* Возвращает URL текущей страницы для Schema.org @id.
|
||
* Динамически через get_permalink() — не зависит от хардкода ID.
|
||
*/
|
||
function dekart_schema_page_url(): string {
|
||
$id = get_the_ID();
|
||
return $id ? get_permalink( $id ) : home_url( '/podgotovka-k-shkole/' );
|
||
}
|
||
|
||
function dekart_schema_output(): void {
|
||
if ( ! is_page_template( 'page-podgotovka-k-shkole.php' ) ) {
|
||
return;
|
||
}
|
||
|
||
if ( ! function_exists( 'carbon_get_post_meta' ) || ! function_exists( 'carbon_get_theme_option' ) ) {
|
||
return;
|
||
}
|
||
|
||
$cache_key = 'dekart_schema_graph_' . get_the_ID() . '_' . determine_locale();
|
||
$cached = wp_cache_get( $cache_key, 'dekart_schema' );
|
||
if ( false !== $cached ) {
|
||
echo $cached;
|
||
return;
|
||
}
|
||
|
||
$graph = array();
|
||
|
||
$webpage = dekart_schema_webpage();
|
||
if ( $webpage ) {
|
||
$graph[] = $webpage;
|
||
}
|
||
|
||
$website = dekart_schema_website();
|
||
if ( $website ) {
|
||
$graph[] = $website;
|
||
}
|
||
|
||
$breadcrumb = dekart_schema_breadcrumb();
|
||
if ( $breadcrumb ) {
|
||
$graph[] = $breadcrumb;
|
||
}
|
||
|
||
$organization = dekart_schema_organization();
|
||
if ( $organization ) {
|
||
$graph[] = $organization;
|
||
}
|
||
|
||
$local_business = dekart_schema_local_business();
|
||
if ( $local_business ) {
|
||
$graph[] = $local_business;
|
||
}
|
||
|
||
$course = dekart_schema_course();
|
||
if ( $course ) {
|
||
$graph[] = $course;
|
||
}
|
||
|
||
$offers = dekart_schema_offer();
|
||
if ( ! empty( $offers ) ) {
|
||
if ( isset( $offers[0] ) && is_array( $offers[0] ) ) {
|
||
foreach ( $offers as $offer ) {
|
||
$graph[] = $offer;
|
||
}
|
||
} else {
|
||
$graph[] = $offers;
|
||
}
|
||
}
|
||
|
||
$rating = dekart_schema_rating();
|
||
if ( $rating ) {
|
||
$graph[] = $rating;
|
||
}
|
||
|
||
$service = dekart_schema_service();
|
||
if ( $service ) {
|
||
$graph[] = $service;
|
||
}
|
||
|
||
$faq = dekart_schema_faq();
|
||
if ( $faq ) {
|
||
$graph[] = $faq;
|
||
}
|
||
|
||
$event = dekart_schema_trial_event();
|
||
if ( $event ) {
|
||
$graph[] = $event;
|
||
}
|
||
|
||
$reviews = dekart_schema_reviews();
|
||
if ( ! empty( $reviews ) && is_array( $reviews ) ) {
|
||
$graph[] = array(
|
||
'@type' => 'ItemList',
|
||
'@id' => dekart_schema_page_url() . '#reviews',
|
||
'name' => 'Отзывы о подготовке к школе',
|
||
'description' => 'Отзывы родителей о курсе подготовки к школе в Детском центре «Декарт»',
|
||
'itemListElement' => array_map( function( $review, $index ) {
|
||
return array(
|
||
'@type' => 'ListItem',
|
||
'position' => $index + 1,
|
||
'item' => $review,
|
||
);
|
||
}, $reviews, array_keys( $reviews ) ),
|
||
'numberOfItems' => count( $reviews ),
|
||
);
|
||
}
|
||
|
||
$teachers = dekart_schema_teachers();
|
||
if ( ! empty( $teachers ) && is_array( $teachers ) ) {
|
||
foreach ( $teachers as $person ) {
|
||
$graph[] = $person;
|
||
}
|
||
}
|
||
|
||
$author = dekart_schema_author();
|
||
if ( $author ) {
|
||
$graph[] = $author;
|
||
}
|
||
|
||
if ( empty( $graph ) ) {
|
||
return;
|
||
}
|
||
|
||
$json = wp_json_encode(
|
||
array(
|
||
'@context' => 'https://schema.org',
|
||
'@graph' => $graph,
|
||
),
|
||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
||
);
|
||
|
||
if ( false === $json ) {
|
||
return;
|
||
}
|
||
|
||
$output = '<script type="application/ld+json">' . "\n" . $json . "\n" . '</script>' . "\n";
|
||
wp_cache_set( $cache_key, $output, 'dekart_schema', 3600 );
|
||
echo $output;
|
||
}
|
||
|
||
/* =====================================================================
|
||
Сущности @graph
|
||
===================================================================== */
|
||
|
||
/**
|
||
* WebPage — текущая страница.
|
||
* @see https://schema.org/WebPage
|
||
*/
|
||
function dekart_schema_webpage(): ?array {
|
||
$post_id = get_the_ID();
|
||
$url = get_permalink( $post_id ) ?: dekart_schema_page_url();
|
||
|
||
$yoast_title = get_post_meta( $post_id, '_yoast_wpseo_title', true );
|
||
$name = $yoast_title ?: wp_get_document_title();
|
||
|
||
$description = get_post_meta( $post_id, '_yoast_wpseo_metadesc', true );
|
||
$description = $description ?: get_post_meta( $post_id, 'rank_math_description', true );
|
||
$description = $description ?: carbon_get_post_meta( $post_id, 'banner_subtitle' );
|
||
$description = $description ?: 'Подготовка к школе для детей 5–7 лет в Щёлково. Чтение, письмо, математика, логика.';
|
||
|
||
$image_url = '';
|
||
if ( $post_id && has_post_thumbnail( $post_id ) ) {
|
||
$image_url = get_the_post_thumbnail_url( $post_id, 'full' );
|
||
}
|
||
|
||
$about_text = carbon_get_post_meta( $post_id, 'pksh_level' ) ?: 'Подготовка к школе';
|
||
$city = dekart_branch_option( 'branch_city', 'Щёлково' );
|
||
|
||
$data = Pksh_Data::instance();
|
||
|
||
$webpage = array(
|
||
'@type' => 'WebPage',
|
||
'@id' => $url . '#webpage',
|
||
'url' => $url,
|
||
'name' => wp_strip_all_tags( $name ),
|
||
'description' => wp_strip_all_tags( $description ),
|
||
'inLanguage' => str_replace( '_', '-', determine_locale() ?: 'ru' ),
|
||
'isPartOf' => array(
|
||
'@id' => home_url( '/' ) . '#website',
|
||
),
|
||
'breadcrumb' => array(
|
||
'@id' => $url . '#breadcrumb',
|
||
),
|
||
'mainEntity' => array(
|
||
'@id' => $url . '#course',
|
||
),
|
||
'speakable' => array(
|
||
'@type' => 'SpeakableSpecification',
|
||
'cssSelector' => array(
|
||
'h1.ds-hero__h1',
|
||
'.ds-hero__subtitle',
|
||
),
|
||
),
|
||
'about' => array(
|
||
'@type' => 'Thing',
|
||
'name' => wp_strip_all_tags( sprintf( '%s в %s', $about_text, $city ) ),
|
||
),
|
||
'keywords' => wp_strip_all_tags(
|
||
'подготовка к школе, дошкольное образование, обучение чтению, обучение письму, '
|
||
. 'математика для дошкольников, развитие логики, курсы для детей 5-7 лет, '
|
||
. $city
|
||
),
|
||
'datePublished' => $data->get_page_publish_date(),
|
||
'dateModified' => $data->get_page_modified_date(),
|
||
'author' => array(
|
||
'@id' => $url . '#author',
|
||
),
|
||
);
|
||
|
||
$faq_items = carbon_get_post_meta( $post_id, 'pksh_faq_items' );
|
||
if ( ! empty( $faq_items ) && is_array( $faq_items ) ) {
|
||
$webpage['hasPart'] = array(
|
||
'@id' => $url . '#faq',
|
||
);
|
||
}
|
||
|
||
return $webpage;
|
||
}
|
||
|
||
/**
|
||
* WebSite — главный сайт.
|
||
*/
|
||
function dekart_schema_website(): ?array {
|
||
$site_name = dekart_branch_option( 'branch_name', 'Детский центр «Декарт»' );
|
||
$home_url = home_url( '/' );
|
||
|
||
return array(
|
||
'@type' => 'WebSite',
|
||
'@id' => $home_url . '#website',
|
||
'url' => $home_url,
|
||
'name' => wp_strip_all_tags( $site_name ),
|
||
'publisher' => array(
|
||
'@id' => $home_url . '#organization',
|
||
),
|
||
'inLanguage' => str_replace( '_', '-', determine_locale() ?: 'ru' ),
|
||
'potentialAction' => array(
|
||
array(
|
||
'@type' => 'SearchAction',
|
||
'target' => array(
|
||
'@type' => 'EntryPoint',
|
||
'urlTemplate' => $home_url . '?s={search_term_string}',
|
||
),
|
||
'query-input' => 'required name=search_term_string',
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* BreadcrumbList — хлебные крошки для страницы.
|
||
*/
|
||
function dekart_schema_breadcrumb(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$name = carbon_get_post_meta( get_the_ID(), 'banner_h1' ) ?: 'Подготовка к школе';
|
||
|
||
return array(
|
||
'@type' => 'BreadcrumbList',
|
||
'@id' => $page_url . '#breadcrumb',
|
||
'itemListElement' => array(
|
||
array(
|
||
'@type' => 'ListItem',
|
||
'position' => 1,
|
||
'name' => 'Главная',
|
||
'item' => home_url( '/' ),
|
||
),
|
||
array(
|
||
'@type' => 'ListItem',
|
||
'position' => 2,
|
||
'name' => wp_strip_all_tags( $name ),
|
||
'item' => $page_url,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Helper: получить значение из Carbon Fields (schema_*) с fallback на Settings API (branch_*).
|
||
*/
|
||
function dekart_schema_option( string $schema_key, string $branch_key, $default = '' ) {
|
||
$val = carbon_get_theme_option( $schema_key );
|
||
if ( ! empty( $val ) ) {
|
||
return $val;
|
||
}
|
||
$val = get_option( $branch_key );
|
||
if ( ! empty( $val ) ) {
|
||
return $val;
|
||
}
|
||
return $default;
|
||
}
|
||
|
||
/**
|
||
* Helper: получить значение из Настроек филиала (branch_*).
|
||
*/
|
||
function dekart_branch_option( string $key, string $default = '' ): string {
|
||
$val = get_option( $key );
|
||
if ( ! empty( $val ) && is_string( $val ) ) {
|
||
return trim( $val );
|
||
}
|
||
return $default;
|
||
}
|
||
|
||
/**
|
||
* Parent Organization — юридическое лицо (без адреса филиала).
|
||
*/
|
||
function dekart_schema_organization(): ?array {
|
||
$home_url = home_url( '/' );
|
||
$brand = dekart_branch_option( 'branch_name', 'Детский центр «Декарт»' );
|
||
|
||
$org = array(
|
||
'@type' => 'Organization',
|
||
'@id' => $home_url . '#organization',
|
||
'name' => wp_strip_all_tags( $brand ),
|
||
'url' => $home_url,
|
||
'logo' => array(
|
||
'@type' => 'ImageObject',
|
||
'url' => dekart_resolve_logo(),
|
||
),
|
||
);
|
||
|
||
$legal_name = dekart_schema_option( 'schema_legal_name', 'branch_legal_name' );
|
||
if ( ! empty( $legal_name ) && is_string( $legal_name ) ) {
|
||
$org['legalName'] = wp_strip_all_tags( trim( $legal_name ) );
|
||
}
|
||
|
||
$cp_phone = dekart_branch_option( 'branch_phone', '' );
|
||
if ( $cp_phone ) {
|
||
$org['contactPoint'] = array(
|
||
'@type' => 'ContactPoint',
|
||
'telephone' => wp_strip_all_tags( $cp_phone ),
|
||
'contactType' => 'customer service',
|
||
'areaServed' => 'RU',
|
||
'availableLanguage' => 'Russian',
|
||
);
|
||
}
|
||
|
||
return $org;
|
||
}
|
||
|
||
/**
|
||
* Helper: цепочка разрешения логотипа.
|
||
*/
|
||
function dekart_resolve_logo(): string {
|
||
$branch_logo = get_option( 'branch_logo' );
|
||
if ( ! empty( $branch_logo ) ) {
|
||
if ( is_array( $branch_logo ) && isset( $branch_logo['url'] ) ) {
|
||
return $branch_logo['url'];
|
||
}
|
||
$url = wp_get_attachment_url( $branch_logo );
|
||
if ( $url ) {
|
||
return $url;
|
||
}
|
||
}
|
||
|
||
$banner_img = carbon_get_post_meta( get_the_ID(), 'banner_img' );
|
||
if ( ! empty( $banner_img ) ) {
|
||
if ( is_array( $banner_img ) && isset( $banner_img['url'] ) ) {
|
||
return $banner_img['url'];
|
||
}
|
||
$url = wp_get_attachment_url( $banner_img );
|
||
if ( $url ) {
|
||
return $url;
|
||
}
|
||
}
|
||
|
||
if ( has_custom_logo() ) {
|
||
$logo = wp_get_attachment_image_url( get_theme_mod( 'custom_logo' ), 'full' );
|
||
if ( $logo ) {
|
||
return $logo;
|
||
}
|
||
}
|
||
|
||
$post_id = get_the_ID();
|
||
if ( $post_id && has_post_thumbnail( $post_id ) ) {
|
||
$url = get_the_post_thumbnail_url( $post_id, 'full' );
|
||
if ( $url ) {
|
||
return $url;
|
||
}
|
||
}
|
||
|
||
return get_template_directory_uri() . '/assets/images/logo-svg.svg';
|
||
}
|
||
|
||
/**
|
||
* LocalBusiness — филиал/центр с адресом, телефоном.
|
||
*/
|
||
function dekart_schema_local_business(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$brand = dekart_branch_option( 'branch_name', 'Детский центр «Декарт»' );
|
||
$street = get_option( 'branch_address' ) ?: carbon_get_theme_option( 'site_address' ) ?: 'Талсинская ул., 24';
|
||
$city = dekart_branch_option( 'branch_city', 'Щёлково' );
|
||
$region = dekart_branch_option( 'branch_region', 'Московская область' );
|
||
$phone = dekart_branch_option( 'branch_phone', '' );
|
||
$email = dekart_branch_option( 'branch_email', '' );
|
||
$coords = get_option( 'branch_coords' );
|
||
$lat = '';
|
||
$lng = '';
|
||
if ( ! empty( $coords ) && is_string( $coords ) && false !== strpos( $coords, ',' ) ) {
|
||
$parts = explode( ',', $coords );
|
||
if ( count( $parts ) >= 2 ) {
|
||
$lat = trim( $parts[0] );
|
||
$lng = trim( $parts[1] );
|
||
}
|
||
}
|
||
$zip = dekart_schema_option( 'schema_postal_code', 'branch_postal_code' );
|
||
$price_range = get_option( 'branch_price_range' );
|
||
$founded = dekart_schema_option( 'schema_founded', 'branch_founded' );
|
||
$map_url = dekart_schema_option( 'schema_map_url', 'branch_map_url' );
|
||
$google_place_id = get_option( 'branch_google_place_id' );
|
||
$google_maps_url = get_option( 'branch_google_maps_url' );
|
||
$area_served_raw = carbon_get_theme_option( 'schema_area_served' ) ?: get_option( 'branch_area_served', 'Щёлково, Фрязино, Монино, Ивантеевка, Королёв' );
|
||
$hours_cf = carbon_get_theme_option( 'schema_hours' );
|
||
|
||
$lb = array(
|
||
'@type' => array( 'EducationalOrganization', 'LocalBusiness' ),
|
||
'@id' => $page_url . '#local-business',
|
||
'parentOrganization' => array(
|
||
'@id' => home_url( '/' ) . '#organization',
|
||
),
|
||
'name' => wp_strip_all_tags( $brand ),
|
||
'address' => array(
|
||
'@type' => 'PostalAddress',
|
||
'streetAddress' => wp_strip_all_tags( $street ),
|
||
'addressLocality' => wp_strip_all_tags( $city ),
|
||
'addressRegion' => wp_strip_all_tags( $region ),
|
||
'addressCountry' => 'RU',
|
||
),
|
||
'url' => $page_url,
|
||
);
|
||
|
||
if ( $phone ) {
|
||
$lb['telephone'] = wp_strip_all_tags( $phone );
|
||
}
|
||
if ( $email ) {
|
||
$lb['email'] = wp_strip_all_tags( $email );
|
||
}
|
||
if ( ! empty( $zip ) && is_string( $zip ) ) {
|
||
$lb['address']['postalCode'] = trim( $zip );
|
||
}
|
||
if ( ! empty( $lat ) && ! empty( $lng ) ) {
|
||
$lb['geo'] = array(
|
||
'@type' => 'GeoCoordinates',
|
||
'latitude' => floatval( $lat ),
|
||
'longitude' => floatval( $lng ),
|
||
);
|
||
}
|
||
if ( ! empty( $google_maps_url ) && is_string( $google_maps_url ) ) {
|
||
$lb['hasMap'] = esc_url( trim( $google_maps_url ) );
|
||
} elseif ( ! empty( $map_url ) && is_string( $map_url ) ) {
|
||
$lb['hasMap'] = esc_url( trim( $map_url ) );
|
||
}
|
||
|
||
$hours_spec = array();
|
||
if ( ! empty( $hours_cf ) && is_array( $hours_cf ) ) {
|
||
foreach ( $hours_cf as $entry ) {
|
||
$day = isset( $entry['day_of_week'] ) ? trim( $entry['day_of_week'] ) : '';
|
||
if ( empty( $day ) ) {
|
||
continue;
|
||
}
|
||
$is_off = ! empty( $entry['day_off'] );
|
||
if ( $is_off ) {
|
||
$hours_spec[] = array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => $day,
|
||
'opens' => '00:00',
|
||
'closes' => '00:00',
|
||
);
|
||
} else {
|
||
$from = isset( $entry['opens'] ) ? trim( $entry['opens'] ) : '';
|
||
$to = isset( $entry['closes'] ) ? trim( $entry['closes'] ) : '';
|
||
if ( $from && $to ) {
|
||
$hours_spec[] = array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => $day,
|
||
'opens' => $from,
|
||
'closes' => $to,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
$hours_raw = get_option( 'branch_hours' );
|
||
if ( ! empty( $hours_raw ) && is_string( $hours_raw ) ) {
|
||
$lines = explode( "\n", $hours_raw );
|
||
foreach ( $lines as $line ) {
|
||
$line = trim( $line );
|
||
if ( empty( $line ) ) {
|
||
continue;
|
||
}
|
||
$parts = explode( '|', $line );
|
||
$day = isset( $parts[0] ) ? trim( $parts[0] ) : '';
|
||
if ( empty( $day ) ) {
|
||
continue;
|
||
}
|
||
if ( isset( $parts[2] ) && 'closed' === strtolower( trim( $parts[2] ) ) ) {
|
||
$hours_spec[] = array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => $day,
|
||
'opens' => '00:00',
|
||
'closes' => '00:00',
|
||
);
|
||
continue;
|
||
}
|
||
$from = isset( $parts[1] ) ? trim( $parts[1] ) : '';
|
||
$to = isset( $parts[2] ) ? trim( $parts[2] ) : '';
|
||
if ( $day && $from && $to ) {
|
||
$hours_spec[] = array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => $day,
|
||
'opens' => $from,
|
||
'closes' => $to,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ( ! empty( $hours_spec ) ) {
|
||
$lb['openingHoursSpecification'] = $hours_spec;
|
||
}
|
||
|
||
if ( ! empty( $price_range ) && is_string( $price_range ) ) {
|
||
$lb['priceRange'] = trim( $price_range );
|
||
}
|
||
|
||
if ( ! empty( $google_place_id ) && is_string( $google_place_id ) ) {
|
||
$lb['identifier'] = array(
|
||
'@type' => 'PropertyValue',
|
||
'name' => 'Google Place ID',
|
||
'value' => wp_strip_all_tags( $google_place_id ),
|
||
);
|
||
$lb['@id'] = 'https://search.google.com/local/writereview?placeid=' . urlencode( $google_place_id );
|
||
}
|
||
|
||
$area_cities = array_map( 'trim', explode( ',', $area_served_raw ) );
|
||
$lb['areaServed'] = array_map( function( $c ) {
|
||
return array( '@type' => 'City', 'name' => wp_strip_all_tags( $c ) );
|
||
}, array_filter( $area_cities ) );
|
||
|
||
if ( ! empty( $founded ) && is_string( $founded ) ) {
|
||
$lb['foundingDate'] = trim( $founded );
|
||
}
|
||
|
||
$social_cf = carbon_get_theme_option( 'schema_social' );
|
||
$same_as = array();
|
||
if ( ! empty( $social_cf ) && is_array( $social_cf ) ) {
|
||
foreach ( $social_cf as $entry ) {
|
||
$url = isset( $entry['url'] ) ? trim( $entry['url'] ) : '';
|
||
if ( $url && filter_var( $url, FILTER_VALIDATE_URL ) ) {
|
||
$same_as[] = esc_url( $url );
|
||
}
|
||
}
|
||
} else {
|
||
$social_raw = get_option( 'branch_social' );
|
||
if ( ! empty( $social_raw ) && is_array( $social_raw ) ) {
|
||
foreach ( $social_raw as $entry ) {
|
||
$url = isset( $entry['url'] ) ? trim( $entry['url'] ) : '';
|
||
if ( $url && filter_var( $url, FILTER_VALIDATE_URL ) ) {
|
||
$same_as[] = esc_url( $url );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ( ! empty( $same_as ) ) {
|
||
$lb['sameAs'] = $same_as;
|
||
}
|
||
|
||
$ensure_platforms = array(
|
||
'WhatsApp' => dekart_branch_option( 'branch_whatsapp', 'https://wa.me/79269311434' ),
|
||
'Telegram' => dekart_branch_option( 'branch_telegram', 'https://t.me/dekart_school' ),
|
||
);
|
||
foreach ( $ensure_platforms as $platform => $url ) {
|
||
if ( ! empty( $url ) && filter_var( $url, FILTER_VALIDATE_URL ) ) {
|
||
$found = false;
|
||
foreach ( $same_as as $existing ) {
|
||
if ( false !== stripos( $existing, parse_url( $url, PHP_URL_HOST ) ) ) {
|
||
$found = true;
|
||
break;
|
||
}
|
||
}
|
||
if ( ! $found ) {
|
||
$same_as[] = esc_url( $url );
|
||
}
|
||
}
|
||
}
|
||
|
||
$gbp_url = get_option( 'branch_google_business_url', '' );
|
||
if ( ! empty( $gbp_url ) && filter_var( $gbp_url, FILTER_VALIDATE_URL ) ) {
|
||
$found_gbp = false;
|
||
foreach ( $same_as as $existing ) {
|
||
if ( false !== stripos( $existing, parse_url( $gbp_url, PHP_URL_HOST ) ) ) {
|
||
$found_gbp = true;
|
||
break;
|
||
}
|
||
}
|
||
if ( ! $found_gbp ) {
|
||
$same_as[] = esc_url( $gbp_url );
|
||
}
|
||
}
|
||
|
||
$yb_url = get_option( 'branch_yandex_business_url', '' );
|
||
if ( ! empty( $yb_url ) && filter_var( $yb_url, FILTER_VALIDATE_URL ) ) {
|
||
$found_yb = false;
|
||
foreach ( $same_as as $existing ) {
|
||
if ( false !== stripos( $existing, parse_url( $yb_url, PHP_URL_HOST ) ) ) {
|
||
$found_yb = true;
|
||
break;
|
||
}
|
||
}
|
||
if ( ! $found_yb ) {
|
||
$same_as[] = esc_url( $yb_url );
|
||
}
|
||
}
|
||
|
||
if ( ! empty( $same_as ) ) {
|
||
$lb['sameAs'] = $same_as;
|
||
}
|
||
|
||
$photos_cf = carbon_get_theme_option( 'schema_photos' );
|
||
$images = array();
|
||
if ( ! empty( $photos_cf ) && is_array( $photos_cf ) ) {
|
||
foreach ( $photos_cf as $id ) {
|
||
if ( ! is_numeric( $id ) || $id <= 0 ) {
|
||
continue;
|
||
}
|
||
$url = wp_get_attachment_url( (int) $id );
|
||
if ( $url ) {
|
||
$images[] = esc_url( $url );
|
||
}
|
||
}
|
||
} else {
|
||
$photos_raw = get_option( 'branch_photos' );
|
||
if ( ! empty( $photos_raw ) && is_string( $photos_raw ) ) {
|
||
$ids = explode( ',', $photos_raw );
|
||
foreach ( $ids as $id ) {
|
||
$id = trim( $id );
|
||
if ( ! is_numeric( $id ) || $id <= 0 ) {
|
||
continue;
|
||
}
|
||
$url = wp_get_attachment_url( (int) $id );
|
||
if ( $url ) {
|
||
$images[] = esc_url( $url );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if ( ! empty( $images ) ) {
|
||
$lb['image'] = $images;
|
||
}
|
||
|
||
$teachers = carbon_get_post_meta( get_the_ID(), 'pksh_teachers' );
|
||
if ( ! empty( $teachers ) && is_array( $teachers ) ) {
|
||
$employee_ids = array();
|
||
foreach ( $teachers as $i => $t ) {
|
||
$t_id = isset( $t['teacher_id'] ) ? intval( $t['teacher_id'] ) : 0;
|
||
if ( $t_id > 0 ) {
|
||
$employee_ids[] = array(
|
||
'@id' => $page_url . '#teacher-' . $i,
|
||
);
|
||
}
|
||
}
|
||
if ( ! empty( $employee_ids ) ) {
|
||
$lb['employee'] = $employee_ids;
|
||
}
|
||
}
|
||
|
||
return $lb;
|
||
}
|
||
|
||
/**
|
||
* Course — основной курс «Подготовка к школе».
|
||
* @see https://schema.org/Course
|
||
*/
|
||
function dekart_schema_course(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$name = carbon_get_post_meta( get_the_ID(), 'banner_h1' ) ?: 'Подготовка к школе 5–7 лет в Щёлково';
|
||
|
||
$pksh_description = carbon_get_post_meta( get_the_ID(), 'pksh_description' );
|
||
$description = ! empty( $pksh_description ) ? $pksh_description : ( carbon_get_post_meta( get_the_ID(), 'banner_subtitle' ) ?: 'Научим читать, считать и писать до школы. Бесплатное пробное занятие.' );
|
||
$has_trial = ! empty( $description ) && false !== mb_stripos( $description, 'бесплатно' );
|
||
|
||
$level = carbon_get_post_meta( get_the_ID(), 'pksh_level' );
|
||
$age = carbon_get_post_meta( get_the_ID(), 'pksh_age' );
|
||
$audience = carbon_get_post_meta( get_the_ID(), 'pksh_audience' );
|
||
$course_mode = carbon_get_post_meta( get_the_ID(), 'pksh_course_mode' );
|
||
$skills = carbon_get_post_meta( get_the_ID(), 'pksh_skills' );
|
||
$course_img = carbon_get_post_meta( get_the_ID(), 'banner_img' );
|
||
$programs = carbon_get_post_meta( get_the_ID(), 'pksh_programs' );
|
||
|
||
$course = array(
|
||
'@type' => 'Course',
|
||
'@id' => $page_url . '#course',
|
||
'name' => wp_strip_all_tags( $name ),
|
||
'description' => wp_strip_all_tags( $description ),
|
||
'url' => $page_url,
|
||
'provider' => array(
|
||
'@id' => $page_url . '#local-business',
|
||
),
|
||
);
|
||
|
||
if ( $has_trial ) {
|
||
$course['hasCourseInstance'] = array(
|
||
'@type' => 'CourseInstance',
|
||
'courseMode' => 'Onsite',
|
||
'courseWorkload' => '30-40 минут',
|
||
);
|
||
}
|
||
|
||
if ( ! empty( $level ) && is_string( $level ) ) {
|
||
$course['educationalLevel'] = wp_strip_all_tags( trim( $level ) );
|
||
}
|
||
if ( ! empty( $age ) && is_string( $age ) ) {
|
||
$course['typicalAgeRange'] = wp_strip_all_tags( trim( $age ) );
|
||
}
|
||
if ( ! empty( $audience ) && is_string( $audience ) ) {
|
||
$course['audience'] = array(
|
||
'@type' => 'EducationalAudience',
|
||
'name' => wp_strip_all_tags( trim( $audience ) ),
|
||
);
|
||
}
|
||
|
||
if ( ! empty( $skills ) && is_array( $skills ) ) {
|
||
$teaches = array();
|
||
foreach ( $skills as $skill ) {
|
||
$s = isset( $skill['skill'] ) ? trim( $skill['skill'] ) : '';
|
||
if ( $s ) {
|
||
$teaches[] = wp_strip_all_tags( $s );
|
||
}
|
||
}
|
||
if ( ! empty( $teaches ) ) {
|
||
$course['teaches'] = $teaches;
|
||
}
|
||
}
|
||
|
||
if ( ! empty( $course_img ) ) {
|
||
if ( is_array( $course_img ) && isset( $course_img['url'] ) ) {
|
||
$course['image'] = esc_url( $course_img['url'] );
|
||
} else {
|
||
$url = wp_get_attachment_url( $course_img );
|
||
if ( $url ) {
|
||
$course['image'] = esc_url( $url );
|
||
}
|
||
}
|
||
} elseif ( has_post_thumbnail( get_the_ID() ) ) {
|
||
$course['image'] = esc_url( get_the_post_thumbnail_url( get_the_ID(), 'full' ) );
|
||
}
|
||
|
||
return $course;
|
||
}
|
||
|
||
/**
|
||
* AggregateRating — рейтинг из отзывов Carbon Fields.
|
||
*/
|
||
function dekart_schema_rating(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$ratings = array();
|
||
$reviews = carbon_get_post_meta( get_the_ID(), 'pksh_reviews_list' );
|
||
|
||
if ( empty( $reviews ) || ! is_array( $reviews ) ) {
|
||
return null;
|
||
}
|
||
|
||
foreach ( $reviews as $review ) {
|
||
$rating = isset( $review['review_rating'] ) ? intval( $review['review_rating'] ) : 0;
|
||
if ( $rating >= 1 && $rating <= 5 ) {
|
||
$ratings[] = $rating;
|
||
}
|
||
}
|
||
|
||
if ( count( $ratings ) < 1 ) {
|
||
return null;
|
||
}
|
||
|
||
$average = round( array_sum( $ratings ) / count( $ratings ), 1 );
|
||
|
||
return array(
|
||
'@type' => 'AggregateRating',
|
||
'@id' => $page_url . '#aggregate-rating',
|
||
'ratingValue' => (string) $average,
|
||
'bestRating' => '5',
|
||
'worstRating' => '1',
|
||
'ratingCount' => (string) count( $ratings ),
|
||
'itemReviewed' => array(
|
||
'@id' => $page_url . '#course',
|
||
),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Service — сущность услуги «Подготовка к школе».
|
||
*/
|
||
function dekart_schema_service(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$name = carbon_get_post_meta( get_the_ID(), 'banner_h1' ) ?: 'Подготовка к школе 5–7 лет в Щёлково';
|
||
|
||
return array(
|
||
'@type' => 'Service',
|
||
'@id' => $page_url . '#service',
|
||
'name' => wp_strip_all_tags( $name ),
|
||
'provider' => array(
|
||
'@id' => $page_url . '#local-business',
|
||
),
|
||
'areaServed' => array(
|
||
'@type' => 'City',
|
||
'name' => dekart_branch_option( 'branch_city', 'Щёлково' ),
|
||
),
|
||
);
|
||
}
|
||
|
||
/**
|
||
* FAQPage — вопросы и ответы из pksh_faq_items.
|
||
*/
|
||
function dekart_schema_faq(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$faq_items = carbon_get_post_meta( get_the_ID(), 'pksh_faq_items' );
|
||
|
||
if ( empty( $faq_items ) || ! is_array( $faq_items ) ) {
|
||
return null;
|
||
}
|
||
|
||
$main_entity = array();
|
||
foreach ( $faq_items as $item ) {
|
||
$q = isset( $item['faq_question'] ) ? trim( $item['faq_question'] ) : '';
|
||
$a = isset( $item['faq_answer'] ) ? trim( $item['faq_answer'] ) : '';
|
||
if ( empty( $q ) || empty( $a ) ) {
|
||
continue;
|
||
}
|
||
$main_entity[] = array(
|
||
'@type' => 'Question',
|
||
'name' => wp_strip_all_tags( $q ),
|
||
'acceptedAnswer' => array(
|
||
'@type' => 'Answer',
|
||
'text' => wp_strip_all_tags( $a ),
|
||
),
|
||
);
|
||
}
|
||
|
||
if ( empty( $main_entity ) ) {
|
||
return null;
|
||
}
|
||
|
||
return array(
|
||
'@type' => 'FAQPage',
|
||
'@id' => $page_url . '#faq',
|
||
'name' => 'Часто задаваемые вопросы о подготовке к школе',
|
||
'mainEntity' => $main_entity,
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Person[] — преподаватели из pksh_teachers complex.
|
||
* Каждый преподаватель — отдельная сущность Person.
|
||
* Связаны с LocalBusiness через employee @id.
|
||
*
|
||
* @return array[] Массив Person-сущностей для @graph.
|
||
*/
|
||
function dekart_schema_teachers(): array {
|
||
$page_url = dekart_schema_page_url();
|
||
$teachers = carbon_get_post_meta( get_the_ID(), 'pksh_teachers' );
|
||
|
||
if ( empty( $teachers ) || ! is_array( $teachers ) ) {
|
||
return array();
|
||
}
|
||
|
||
$result = array();
|
||
foreach ( $teachers as $i => $teacher ) {
|
||
$t_id = isset( $teacher['teacher_id'] ) ? intval( $teacher['teacher_id'] ) : 0;
|
||
$subject = isset( $teacher['teacher_subject'] ) ? trim( $teacher['teacher_subject'] ) : '';
|
||
$about = isset( $teacher['teacher_about'] ) ? trim( $teacher['teacher_about'] ) : '';
|
||
|
||
if ( $t_id < 1 ) {
|
||
continue;
|
||
}
|
||
|
||
$t_post = get_post( $t_id );
|
||
if ( ! $t_post ) {
|
||
continue;
|
||
}
|
||
$name = $t_post->post_title;
|
||
|
||
if ( empty( $name ) ) {
|
||
continue;
|
||
}
|
||
|
||
$photo = get_post_meta( $t_id, '_teacher_avatar', true );
|
||
if ( ! $photo ) {
|
||
$photo = get_post_meta( $t_id, '_thumbnail_id', true );
|
||
}
|
||
|
||
if ( empty( $subject ) ) {
|
||
$subject = get_post_meta( $t_id, '_teacher_direction', true );
|
||
}
|
||
if ( empty( $about ) ) {
|
||
$about = get_post_meta( $t_id, '_teacher_about', true );
|
||
}
|
||
|
||
$person = array(
|
||
'@type' => 'Person',
|
||
'@id' => $page_url . '#teacher-' . $i,
|
||
'name' => wp_strip_all_tags( $name ),
|
||
);
|
||
|
||
if ( ! empty( $subject ) && is_string( $subject ) ) {
|
||
$person['jobTitle'] = wp_strip_all_tags( trim( $subject ) );
|
||
}
|
||
|
||
if ( ! empty( $about ) && is_string( $about ) ) {
|
||
$person['description'] = wp_strip_all_tags( trim( $about ) );
|
||
}
|
||
|
||
if ( ! empty( $photo ) ) {
|
||
$url = wp_get_attachment_url( (int) $photo );
|
||
if ( $url ) {
|
||
$person['image'] = esc_url( $url );
|
||
}
|
||
}
|
||
|
||
$result[] = $person;
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Review[] — поштучные отзывы из pksh_reviews_list.
|
||
* Каждый отзыв — отдельная сущность Review с автор-персоной и оценкой.
|
||
*
|
||
* @return array[] Массив Review-сущностей для @graph.
|
||
*/
|
||
function dekart_schema_reviews(): array {
|
||
$page_url = dekart_schema_page_url();
|
||
$reviews = carbon_get_post_meta( get_the_ID(), 'pksh_reviews_list' );
|
||
|
||
if ( empty( $reviews ) || ! is_array( $reviews ) ) {
|
||
return array();
|
||
}
|
||
|
||
$result = array();
|
||
$review_seq = 0;
|
||
foreach ( $reviews as $i => $review ) {
|
||
$author_name = isset( $review['review_author'] ) ? trim( $review['review_author'] ) : '';
|
||
$body = isset( $review['review_text'] ) ? trim( $review['review_text'] ) : '';
|
||
$rating_val = isset( $review['review_rating'] ) ? intval( $review['review_rating'] ) : 0;
|
||
|
||
if ( empty( $author_name ) || empty( $body ) ) {
|
||
continue;
|
||
}
|
||
if ( $rating_val < 1 || $rating_val > 5 ) {
|
||
continue;
|
||
}
|
||
|
||
$review_seq++;
|
||
|
||
$entity = array(
|
||
'@type' => 'Review',
|
||
'@id' => $page_url . '#review-' . $review_seq,
|
||
'author' => array(
|
||
'@type' => 'Person',
|
||
'name' => wp_strip_all_tags( $author_name ),
|
||
),
|
||
'reviewBody' => wp_strip_all_tags( $body ),
|
||
'itemReviewed' => array(
|
||
'@id' => $page_url . '#course',
|
||
),
|
||
'reviewRating' => array(
|
||
'@type' => 'Rating',
|
||
'ratingValue' => (string) $rating_val,
|
||
'bestRating' => '5',
|
||
'worstRating' => '1',
|
||
),
|
||
);
|
||
|
||
$review_date = isset( $review['review_date'] ) ? trim( $review['review_date'] ) : '';
|
||
if ( $review_date ) {
|
||
$entity['datePublished'] = sanitize_text_field( $review_date );
|
||
}
|
||
|
||
$result[] = $entity;
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
|
||
/**
|
||
* Author Person — автор контента страницы.
|
||
* Берётся из CF полей вкладки "🤖 GEO (AI-поиск)".
|
||
*/
|
||
function dekart_schema_author(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$data = Pksh_Data::instance();
|
||
$name = $data->get_author_name();
|
||
$years = $data->get_years_on_market();
|
||
|
||
// Должность — хардкор + авто-расчёт лет
|
||
$title = 'Образовательный центр с гослицензией';
|
||
if ( $years > 0 ) {
|
||
$title .= ', ' . $years . ' лет на рынке';
|
||
}
|
||
|
||
$person = array(
|
||
'@type' => 'Person',
|
||
'@id' => $page_url . '#author',
|
||
'name' => wp_strip_all_tags( $name ),
|
||
'jobTitle' => wp_strip_all_tags( $title ),
|
||
);
|
||
|
||
$person['description'] = wp_strip_all_tags( sprintf(
|
||
'Автор контента %s — %s',
|
||
$name,
|
||
$title
|
||
) );
|
||
|
||
return $person;
|
||
}
|
||
|
||
/**
|
||
* Event — бесплатное пробное занятие.
|
||
* @see https://schema.org/Event
|
||
*/
|
||
function dekart_schema_trial_event(): ?array {
|
||
if ( ! is_page_template( 'page-podgotovka-k-shkole.php' ) ) {
|
||
return null;
|
||
}
|
||
|
||
$page_url = dekart_schema_page_url();
|
||
|
||
$subtitle = carbon_get_post_meta( get_the_ID(), 'banner_subtitle' );
|
||
$has_trial = ! empty( $subtitle ) && false !== mb_stripos( $subtitle, 'бесплатно' );
|
||
|
||
if ( ! $has_trial ) {
|
||
return null;
|
||
}
|
||
|
||
$start_date = carbon_get_post_meta( get_the_ID(), 'pksh_trial_event_start_date' );
|
||
if ( empty( $start_date ) ) {
|
||
$start_date = date( 'c', strtotime( 'next monday 10:00' ) );
|
||
}
|
||
|
||
$end_date = carbon_get_post_meta( get_the_ID(), 'pksh_trial_event_end_date' );
|
||
if ( empty( $end_date ) ) {
|
||
$end_date = date( 'c', strtotime( $start_date . ' +1 hour' ) );
|
||
}
|
||
|
||
$location = array(
|
||
'@type' => 'Place',
|
||
'name' => 'Детский центр «Декарт»',
|
||
'address' => array(
|
||
'@type' => 'PostalAddress',
|
||
'streetAddress' => get_option( 'branch_address' ) ?: carbon_get_theme_option( 'site_address' ),
|
||
'addressLocality' => get_option( 'branch_city', 'Щёлково' ),
|
||
'addressRegion' => get_option( 'branch_region', 'Московская область' ),
|
||
'addressCountry' => 'RU',
|
||
),
|
||
);
|
||
|
||
$post_id = get_the_ID();
|
||
|
||
return array(
|
||
'@type' => 'Event',
|
||
'@id' => $page_url . '#trial-event',
|
||
'name' => 'Бесплатное пробное занятие: Подготовка к школе',
|
||
'description' => 'Полноценное занятие + диагностика готовности к школе. Ребёнок познакомится с педагогом, выполнит тестовые задания. Родители получат план подготовки.',
|
||
'eventStatus' => 'https://schema.org/EventScheduled',
|
||
'eventAttendanceMode' => 'https://schema.org/OfflineEventAttendanceMode',
|
||
'startDate' => $start_date,
|
||
'endDate' => $end_date,
|
||
'location' => $location,
|
||
'offers' => array(
|
||
'@type' => 'Offer',
|
||
'@id' => $page_url . '#offer-trial',
|
||
'price' => '0',
|
||
'priceCurrency' => 'RUB',
|
||
'availability' => 'https://schema.org/LimitedAvailability',
|
||
'description' => 'Бесплатное пробное занятие',
|
||
'category' => 'Бесплатное пробное занятие',
|
||
),
|
||
'organizer' => array(
|
||
'@id' => home_url( '/' ) . '#organization',
|
||
),
|
||
'image' => ( $post_id && has_post_thumbnail( $post_id ) )
|
||
? get_the_post_thumbnail_url( $post_id, 'full' )
|
||
: '',
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Offer / AggregateOffer с UnitPriceSpecification.
|
||
* @see https://schema.org/UnitPriceSpecification
|
||
*/
|
||
function dekart_schema_offer(): ?array {
|
||
$page_url = dekart_schema_page_url();
|
||
$base_price = carbon_get_post_meta( get_the_ID(), 'pksh_prog_base_price_sub' );
|
||
$prem_price = carbon_get_post_meta( get_the_ID(), 'pksh_prog_prem_price_sub' );
|
||
$price_valid = carbon_get_post_meta( get_the_ID(), 'pksh_price_valid_until' );
|
||
$offers = array();
|
||
$prices = array();
|
||
|
||
foreach ( array( $base_price, $prem_price ) as $raw ) {
|
||
if ( ! empty( $raw ) && is_string( $raw ) ) {
|
||
$parsed = dekart_parse_price( $raw );
|
||
if ( $parsed > 0 ) {
|
||
$prices[] = $parsed;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( empty( $prices ) ) {
|
||
$offer = array(
|
||
'@type' => 'Offer',
|
||
'@id' => $page_url . '#offer',
|
||
'price' => '0',
|
||
'priceCurrency' => 'RUB',
|
||
'description' => 'Подготовка к школе — свяжитесь для уточнения стоимости',
|
||
'availability' => 'https://schema.org/InStock',
|
||
'category' => 'Образовательные услуги',
|
||
);
|
||
if ( ! empty( $price_valid ) ) {
|
||
$offer['priceValidUntil'] = trim( $price_valid );
|
||
}
|
||
$offers[] = $offer;
|
||
return $offers;
|
||
}
|
||
|
||
$low = min( $prices );
|
||
$high = max( $prices );
|
||
|
||
$aggregate = array(
|
||
'@type' => 'AggregateOffer',
|
||
'@id' => $page_url . '#offer',
|
||
'name' => 'Стоимость подготовки к школе',
|
||
'lowPrice' => (string) $low,
|
||
'highPrice' => (string) $high,
|
||
'offerCount' => (string) count( $prices ),
|
||
'availability' => 'https://schema.org/InStock',
|
||
'category' => 'Образовательные услуги',
|
||
'offeredBy' => array(
|
||
'@id' => $page_url . '#local-business',
|
||
),
|
||
'priceSpecification' => array(
|
||
'@type' => 'UnitPriceSpecification',
|
||
'name' => 'Абонемент за 4 недели',
|
||
'minPrice' => (string) $low,
|
||
'maxPrice' => (string) $high,
|
||
'unitCode' => 'MON',
|
||
'unitText' => 'месяц',
|
||
),
|
||
);
|
||
|
||
if ( ! empty( $price_valid ) ) {
|
||
$aggregate['priceValidUntil'] = trim( $price_valid );
|
||
}
|
||
|
||
$offers[] = $aggregate;
|
||
|
||
$subtitle = carbon_get_post_meta( get_the_ID(), 'banner_subtitle' );
|
||
if ( ! empty( $subtitle ) && false !== mb_stripos( $subtitle, 'бесплатно' ) ) {
|
||
$trial = array(
|
||
'@type' => 'Offer',
|
||
'@id' => $page_url . '#offer-trial',
|
||
'price' => '0',
|
||
'priceCurrency' => 'RUB',
|
||
'availability' => 'https://schema.org/LimitedAvailability',
|
||
'description' => wp_strip_all_tags( $subtitle ),
|
||
'category' => 'Бесплатное пробное занятие',
|
||
'offeredBy' => array(
|
||
'@id' => $page_url . '#local-business',
|
||
),
|
||
);
|
||
if ( ! empty( $price_valid ) ) {
|
||
$trial['priceValidUntil'] = trim( $price_valid );
|
||
}
|
||
$offers[] = $trial;
|
||
}
|
||
|
||
return $offers;
|
||
}
|
||
|
||
/**
|
||
* Парсит цену из форматированной строки (например "7 500 ₽" → 7500).
|
||
*/
|
||
function dekart_parse_price( string $raw ): float {
|
||
$clean = preg_replace( '/[^0-9.,]/', '', $raw );
|
||
|
||
if ( empty( $clean ) ) {
|
||
return 0.0;
|
||
}
|
||
|
||
$last_dot = strrpos( $clean, '.' );
|
||
$last_comma = strrpos( $clean, ',' );
|
||
|
||
if ( false !== $last_comma && ( false === $last_dot || $last_comma > $last_dot ) ) {
|
||
$clean = str_replace( '.', '', $clean );
|
||
$clean = str_replace( ',', '.', $clean );
|
||
} else {
|
||
$clean = str_replace( ',', '', $clean );
|
||
$clean = preg_replace( '/\.(?=.*\.)/', '', $clean );
|
||
}
|
||
|
||
return (float) $clean;
|
||
}
|