array(),\n 'body' => '{"status":"ok"}',\n 'response' => array(\n 'code' => 200,\n 'message' => 'OK',\n ),\n 'cookies' => array(),\n 'filename' => null,\n );\n }\n return $pre;\n}, 10, 3 );\n\n// ─────────────────────────────────────────────\n// 4. БАГАТОМОВНЕ СОРТУВАННЯ КАТАЛОГУ ПОСЛУГ ЗА ПЕРЕГЛЯДАМИ\n// ─────────────────────────────────────────────\nif ( ! function_exists( 'jcp_get_multilingual_term_views' ) ) {\n function jcp_get_multilingual_term_views( $term_id ) {\n $term_id = (int) $term_id;\n $views = get_term_meta( $term_id, 'jc_total_views', true );\n \n if ( $views !== '' && $views !== false && (int) $views > 0 ) {\n return (int) $views;\n }\n \n // Якщо це перекладена категорія (WPML), підтягуємо перегляди з оригінальної української категорії\n global $wpdb;\n $sql_orig = $wpdb->prepare("\n SELECT tt_orig.term_id\n FROM {$wpdb->term_taxonomy} tt_curr\n JOIN {$wpdb->prefix}icl_translations tr_curr ON tr_curr.element_id = tt_curr.term_taxonomy_id AND tr_curr.element_type = 'tax_product_cat'\n JOIN {$wpdb->prefix}icl_translations tr_orig ON tr_orig.trid = tr_curr.trid AND tr_orig.element_type = 'tax_product_cat' AND tr_orig.language_code = 'uk'\n JOIN {$wpdb->term_taxonomy} tt_orig ON tt_orig.term_taxonomy_id = tr_orig.element_id\n WHERE tt_curr.term_id = %d\n LIMIT 1\n ", $term_id);\n \n $orig_id = (int) $wpdb->get_var( $sql_orig );\n if ( $orig_id && $orig_id !== $term_id ) {\n $orig_views = (int) get_term_meta( $orig_id, 'jc_total_views', true );\n if ( $orig_views > 0 ) {\n return $orig_views;\n }\n }\n \n return (int) $views;\n }\n}\n\nif ( ! function_exists( 'jcp_get_multilingual_post_views' ) ) {\n /**\n * Отримує кількість переглядів послуги (товару) з урахуванням багатомовності WPML.\n * Якщо у перекладеної послуги 0 переглядів, підтягує перегляди оригінальної послуги (UK).\n */\n function jcp_get_multilingual_post_views( $post_id ) {\n $post_id = (int) $post_id;\n $views = function_exists( 'pvc_get_post_views' ) ? (int) pvc_get_post_views( $post_id ) : 0;\n \n if ( $views > 0 ) {\n return $views;\n }\n \n // Якщо це перекладений товар (WPML), шукаємо оригінальний український товар\n global $wpdb;\n $sql_orig = $wpdb->prepare("\n SELECT tr_orig.element_id\n FROM {$wpdb->prefix}icl_translations tr_curr\n JOIN {$wpdb->prefix}icl_translations tr_orig ON tr_orig.trid = tr_curr.trid AND tr_orig.element_type = tr_curr.element_type AND tr_orig.language_code = 'uk'\n WHERE tr_curr.element_id = %d AND tr_curr.element_type = 'post_product'\n LIMIT 1\n ", $post_id);\n \n $orig_id = (int) $wpdb->get_var( $sql_orig );\n if ( $orig_id && $orig_id !== $post_id ) {\n $orig_views = function_exists( 'pvc_get_post_views' ) ? (int) pvc_get_post_views( $orig_id ) : 0;\n if ( $orig_views > 0 ) {\n return $orig_views;\n }\n }\n \n return $views;\n }\n}\n\nadd_filter( 'woocommerce_get_product_subcategories', function( $categories, $parent_id ) {\n if ( empty( $categories ) || ! is_array( $categories ) ) {\n return $categories;\n }\n \n usort( $categories, function( $a, $b ) {\n $views_a = jcp_get_multilingual_term_views( $a->term_id );\n $views_b = jcp_get_multilingual_term_views( $b->term_id );\n \n if ( $views_a === $views_b ) {\n return strcmp( $a->name, $b->name );\n }\n return ( $views_a > $views_b ) ? -1 : 1;\n } );\n \n return $categories;\n}, 999, 2 );\n\n\n// END ENQUEUE PARENT ACTION\n// 5. ПІДКЛЮЧЕННЯ СТИЛІВ АДВОКАТІВ (ADVOCAT)\nadd_action( 'wp_enqueue_scripts', function() {\n if ( is_singular( 'advocat' ) || is_post_type_archive( 'advocat' ) || is_tax( 'adv_loc' ) || get_query_var( 'advocat_main' ) || get_query_var( 'advocat_location' ) ) {\n $adv_css = get_stylesheet_directory() . '/advocat/advocat.css';\n $adv_ver = file_exists( $adv_css ) ? filemtime( $adv_css ) : '1.2.0';\n wp_enqueue_style( 'advocat-css', get_stylesheet_directory_uri() . '/advocat/advocat.css', array('jcp-unified-ds'), $adv_ver );\n }\n}, 20 );\n// Підключення шорткодів адвокатів\nrequire_once get_stylesheet_directory() . '/advocat/advocat-shortcodes.php';\nrequire_once get_stylesheet_directory() . '/advocat-api.php';\n// Підключення структури URL адвокатів\nrequire_once get_stylesheet_directory() . '/advocat/advocat-rewrite.php';\nrequire_once get_stylesheet_directory() . '/gov_post/gov-rewrite.php';\n// Підключення стилів для держустанов (GOV)\nadd_action( 'wp_enqueue_scripts', function() {\n if ( is_singular( 'gov' ) || is_post_type_archive( 'gov' ) || is_tax( 'gov_type' ) || is_tax( 'location' ) || get_query_var( 'gov_main' ) ) {\n wp_enqueue_style( 'gov-catalog-css', get_stylesheet_directory_uri() . '/gov_post/gov-catalog.css', array(), '1.1' );\n }\n}, 20 );\n\n\n\n// ─────────────────────────────────────────────\n// 6. ПІДКЛЮЧЕННЯ WOOCOMMERCE SINGLE PRODUCT TWEAKS & WIDGETS\n// ─────────────────────────────────────────────\nrequire_once get_stylesheet_directory() . '/woocommerce-single-product-tweaks.php';\nrequire_once get_stylesheet_directory() . '/jcp-consult-block.php';\nrequire_once get_stylesheet_directory() . '/author-carousel.php';\nrequire_once get_stylesheet_directory() . '/floating-contact-buttons.php';\nrequire_once get_stylesheet_directory() . '/bitrix24-widget.php';\nrequire_once get_stylesheet_directory() . '/theme-footer.php';\n\n// Single product styles now loaded via woocommerce-single-product.css in child theme\n\n\n// ─────────────────────────────────────────────\n// ─────────────────────────────────────────────\n// ─────────────────────────────────────────────\n\n\nrequire_once __DIR__ . '/get-post-by-url.php';\n\n\n\nrequire_once __DIR__ . '/n8n-webhook.php';\nrequire_once __DIR__ . '/cf7-webhook.php';\n\n// ─────────────────────────────────────────────\n// 6. ПІДКЛЮЧЕННЯ СТИЛІВ ДЕРЖАВНИХ УСТАНОВ (GOV)\n// ─────────────────────────────────────────────\nadd_action( 'wp_enqueue_scripts', function() {\n if ( is_singular( 'gov' ) || is_post_type_archive( 'gov' ) || is_tax( 'gov_type' ) || is_tax( 'location' ) || is_tax( 'gov_structure' ) || get_query_var( 'gov_main' ) || get_query_var( 'gov_tax_slug' ) || get_query_var( 'gov_tax_child' ) || ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '/gov' ) !== false ) ) {\n wp_enqueue_style( 'gov-catalog-css', get_stylesheet_directory_uri() . '/gov_post/gov-catalog.css', array(), '1.0.5' );\n wp_enqueue_style( 'gov-catalog-root-css', get_stylesheet_directory_uri() . '/gov-catalog.css', array(), '1.0.5' );\n }\n}, 20 );\n\n// ─────────────────────────────────────────────\n// 7. АВТОМАТИЧНЕ ДОДАВАННЯ КЛАСІВ body.gov-page ТА body.advocat-page\n// ─────────────────────────────────────────────\nadd_filter( 'body_class', function( $classes ) {\n if ( is_singular( 'gov' ) || is_post_type_archive( 'gov' ) || is_tax( 'location' ) || is_tax( 'gov_type' ) || is_tax( 'gov_structure' ) || get_query_var( 'gov_main' ) || get_query_var( 'gov_tax_slug' ) || get_query_var( 'gov_tax_child' ) || ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '/gov' ) !== false ) ) {\n if ( ! in_array( 'gov-page', $classes ) ) {\n $classes[] = 'gov-page';\n }\n }\n if ( is_singular( 'advocat' ) || is_post_type_archive( 'advocat' ) || is_tax( 'adv_loc' ) || get_query_var( 'advocat_main' ) || get_query_var( 'advocat_location' ) || ( isset( $_SERVER['REQUEST_URI'] ) && strpos( $_SERVER['REQUEST_URI'], '/advocat' ) !== false ) ) {\n if ( ! in_array( 'advocat-page', $classes ) ) {\n $classes[] = 'advocat-page';\n }\n }\n return $classes;\n} );\n\n// ─────────────────────────────────────────────\n// 8. ДИНАМІЧНИЙ ВИВІД КАРТКИ PDF-ДОКУМЕНТА (ВІДЮРКОНСАЛТ)\n// ─────────────────────────────────────────────\nadd_filter( 'the_content', 'jc_insert_pdf_document_block', 14 );\n\nfunction jc_insert_pdf_document_block( $content ) {\n if ( is_singular( 'post' ) || is_singular( 'victory_case' ) || is_singular( 'product' ) ) {\n $post_id = get_the_ID();\n \n // WPML підтримка\n if ( has_filter( 'wpml_original_element_id' ) ) {\n $original_id = apply_filters( 'wpml_original_element_id', NULL, $post_id, 'post_' . get_post_type( $post_id ) );\n if ( $original_id ) { $post_id = $original_id; }\n }\n \n $pdf_url = get_post_meta( $post_id, 'jc_pdf_document_url', true );\n $pdf_title = get_post_meta( $post_id, 'jc_pdf_document_title', true );\n \n if ( ! empty( $pdf_url ) ) {\n $default_pdf_title = (defined("ICL_LANGUAGE_CODE") && ICL_LANGUAGE_CODE == 'ru') ? 'Скачать официальный образец документа' : 'Завантажити офіційний зразок документа';\n if ( empty( $pdf_title ) ) {\n $pdf_title = $default_pdf_title;\n }\n \n $doc_label = (defined("ICL_LANGUAGE_CODE") && ICL_LANGUAGE_CODE == 'ru') ? '📄 Образец документа' : '📄 Зразок документа';\n $btn_label = (defined("ICL_LANGUAGE_CODE") && ICL_LANGUAGE_CODE == 'ru') ? '👁 Смотреть / Скачать PDF' : '👁 Переглянути / Завантажити PDF';\n \n $pdf_html = '\n
\n
\n
\n
\n ' . $doc_label . '\n
' . esc_html( $pdf_title ) . '
\n \n
\n
\n
';\n \n $pattern = '/= 2 ) {\n $pos = $matches[0][1][1];\n $content = substr_replace( $content, $pdf_html . 'set_404();\n status_header(404);\n wp_die( __('RSS-фіди відключені на цьому сайті. Поверніться на головну сторінку.') );\n }\n}\n\n// ============================================================\n// 8. ПРОФЕСІЙНИЙ ВИВІД АВТОРА ТА ДАТИ (HEADER ENTRY-META)\n// ============================================================\nadd_filter( 'generate_post_author_output', function( $output ) {\n $author_id = get_post_field( 'post_author', get_the_ID() );\n if ( ! $author_id ) {\n $author_id = get_the_author_meta( 'ID' );\n }\n\n $author_name = get_the_author_meta( 'display_name', $author_id );\n if ( empty( $author_name ) ) {\n $author_name = get_the_author();\n }\n\n $author_url = get_author_posts_url( $author_id );\n $avatar = get_avatar( $author_id, 46, '', $author_name, array( 'class' => 'author-avatar-img' ) );\n\n return sprintf(\n '%3$sАвтор:%4$s',\n esc_url( $author_url ),\n esc_attr( $author_name ),\n $avatar,\n esc_html( $author_name )\n );\n} );\n\nadd_filter( 'generate_post_date_output', function( $output, $time_string ) {\n $published_time = get_the_time( 'U' );\n $updated_time = get_the_modified_time( 'U' );\n $published_date = get_the_date( 'd.m.Y' );\n $modified_date = get_the_modified_date( 'd.m.Y' );\n\n $has_update = ( $updated_time > $published_time && ( $updated_time - $published_time > 86400 ) );\n\n $date_html = sprintf(\n '',\n esc_attr( get_the_date( 'c' ) ),\n esc_html( $published_date )\n );\n\n if ( $has_update ) {\n $date_html .= sprintf(\n '·Оновлено: ',\n esc_attr( get_the_modified_date( 'c' ) ),\n esc_html( $modified_date )\n );\n } else {\n $date_html .= sprintf(\n '',\n esc_attr( get_the_modified_date( 'c' ) ),\n esc_html( $modified_date )\n );\n }\n\n return sprintf(\n '📅%1$s',\n $date_html\n );\n}, 10, 2 );\n\n// ============================================================\n// 9. ВІДОБРАЖЕННЯ ТА СОРТУВАННЯ ДАТИ ОНОВЛЕННЯ В АДМІНЦІ\n// ============================================================\n// 1. Додаємо колонку "Оновлено" одразу після колонки "Дата"\nfunction jcp_add_modified_column( $columns ) {\n $new_columns = array();\n foreach ( $columns as $key => $title ) {\n $new_columns[$key] = $title;\n if ( 'date' === $key ) {\n $new_columns['post_modified_date'] = 'Оновлено';\n }\n }\n if ( ! isset( $new_columns['post_modified_date'] ) ) {\n $new_columns['post_modified_date'] = 'Оновлено';\n }\n return $new_columns;\n}\nadd_filter( 'manage_post_posts_columns', 'jcp_add_modified_column' );\nadd_filter( 'manage_page_posts_columns', 'jcp_add_modified_column' );\nadd_filter( 'manage_victory_case_posts_columns', 'jcp_add_modified_column' );\nadd_filter( 'manage_product_posts_columns', 'jcp_add_modified_column' );\n\n// 2. Виводимо дату та час оновлення\nfunction jcp_display_modified_column( $column_name, $post_id ) {\n if ( 'post_modified_date' !== $column_name ) {\n return;\n }\n\n $post = get_post( $post_id );\n if ( ! $post ) {\n return;\n }\n\n $pub_ts = strtotime( $post->post_date );\n $mod_ts = strtotime( $post->post_modified );\n\n // Чи оновлювався запис після публікації (з зазором у 60 секунд)\n $is_modified = ( $mod_ts > ( $pub_ts + 60 ) );\n\n $date_formatted = get_post_modified_time( 'd.m.Y', false, $post_id, true );\n $time_formatted = get_post_modified_time( 'H:i', false, $post_id, true );\n\n if ( $is_modified ) {\n printf(\n '%1$s
%2$s',\n esc_html( $date_formatted ),\n esc_html( $time_formatted )\n );\n } else {\n printf(\n '%1$s
%2$s',\n esc_html( $date_formatted ),\n esc_html( $time_formatted )\n );\n }\n}\nadd_action( 'manage_posts_custom_column', 'jcp_display_modified_column', 10, 2 );\nadd_action( 'manage_pages_custom_column', 'jcp_display_modified_column', 10, 2 );\n\n// 3. Додаємо сортування за датою оновлення\nfunction jcp_sortable_modified_column( $columns ) {\n $columns['post_modified_date'] = 'modified';\n return $columns;\n}\nadd_filter( 'manage_edit-post_sortable_columns', 'jcp_sortable_modified_column' );\nadd_filter( 'manage_edit-page_sortable_columns', 'jcp_sortable_modified_column' );\nadd_filter( 'manage_edit-victory_case_sortable_columns', 'jcp_sortable_modified_column' );\nadd_filter( 'manage_edit-product_sortable_columns', 'jcp_sortable_modified_column' );\n\n// 4. Стилізація ширини колонки в адмін-панелі\nadd_action( 'admin_head', function() {\n echo '';\n} );\n\n// ─────────────────────────────────────────────\n// 5. ПІДТРИМКА RANK MATH ТА КАСТОМНИЙ REST API ДЛЯ MCP / N8N\n// ─────────────────────────────────────────────\nadd_filter( 'rank_math/rest/is_supported_post_type', '__return_true', 99 );\nadd_filter( 'rank_math/paper/auto_post_types', function( $types ) {\n $types = (array) $types;\n return array_unique( array_merge( $types, array( 'post', 'page', 'product', 'victory_case', 'advocat', 'gov', 'creditor' ) ) );\n}, 99 );\n\nif ( ! function_exists( 'jc_register_rank_math_meta_endpoint' ) ) {\n add_action( 'rest_api_init', 'jc_register_rank_math_meta_endpoint', 10 );\n function jc_register_rank_math_meta_endpoint() {\n register_rest_route( 'rank-math-api/v1', '/update-meta', array(\n 'methods' => array( 'POST', 'PUT' ),\n 'callback' => 'jc_handle_rank_math_update_meta',\n 'permission_callback' => '__return_true'\n ));\n }\n}\n\nif ( ! function_exists( 'jc_handle_rank_math_update_meta' ) ) {\n function jc_handle_rank_math_update_meta( $request ) {\n $post_id = $request->get_param( 'post_id' ) ?: $request->get_param( 'id' );\n $title = $request->get_param( 'rank_math_title' ) ?: $request->get_param( 'rank_title' );\n $description = $request->get_param( 'rank_math_description' ) ?: $request->get_param( 'rank_description' );\n $keyword = $request->get_param( 'rank_math_focus_keyword' ) ?: $request->get_param( 'rank_focus_keyword' );\n\n if ( empty( $post_id ) ) {\n return new WP_Error( 'missing_post_id', 'Параметр post_id є обов\'язковим', array( 'status' => 400 ) );\n }\n\n $post_id = absint( $post_id );\n $post = get_post( $post_id );\n if ( ! $post ) {\n return new WP_Error( 'invalid_post_id', 'Пост не знайдено', array( 'status' => 404 ) );\n }\n\n $updated_fields = array();\n\n if ( ! empty( $title ) ) {\n update_post_meta( $post_id, 'rank_math_title', sanitize_text_field( wp_unslash( $title ) ) );\n $updated_fields[] = 'rank_math_title';\n }\n \n if ( ! empty( $description ) ) {\n update_post_meta( $post_id, 'rank_math_description', sanitize_textarea_field( wp_unslash( $description ) ) );\n $updated_fields[] = 'rank_math_description';\n }\n \n if ( ! empty( $keyword ) ) {\n update_post_meta( $post_id, 'rank_math_focus_keyword', sanitize_text_field( wp_unslash( $keyword ) ) );\n $updated_fields[] = 'rank_math_focus_keyword';\n }\n\n return rest_ensure_response( array(\n 'success' => true,\n 'message' => 'SEO дані Rank Math успішно оновлено!',\n 'post_id' => $post_id,\n 'updated_fields' => $updated_fields\n ));\n }\n}\n\n\n// FRONTEND COMMENT MANAGEMENT\nrequire_once __DIR__ . '/frontend-comment-management.php';\n\n// Включення швидкої зміни категорій\nrequire_once get_stylesheet_directory() . '/frontend-category-switcher.php';\n\n// Форма Бітрікс24 для сторінок Арешти\nrequire_once get_stylesheet_directory() . '/bitrix-areshty-form.php';\n\n// Rank Math Google Search Console Analytics API для n8n та мегапромпту\nrequire_once get_stylesheet_directory() . '/rankmath-gsc-api.php';\n\n\n// Fix n8n Get a post node (which always requests /wp/v2/posts/{id}) to work with custom post types!\nadd_filter( "rest_pre_dispatch", function( $result, $server, $request ) {\n $route = $request->get_route();\n \n // Intercept GET /wp/v2/posts/{id}\n if ( preg_match( "#^/wp/v2/posts/(\d+)$#", $route, $matches ) && $request->get_method() === "GET" ) {\n $post_id = (int) $matches[1];\n $post = get_post( $post_id );\n \n // If post exists but is NOT a post, wp/v2/posts will throw 404 rest_post_invalid_id.\n // We rewrite the request to the correct REST route!\n if ( $post && $post->post_type !== "post" ) {\n $post_type_obj = get_post_type_object( $post->post_type );\n if ( !empty($post_type_obj->show_in_rest) ) {\n $rest_base = !empty($post_type_obj->rest_base) ? $post_type_obj->rest_base : $post_type_obj->name;\n \n $new_route = "/wp/v2/" . $rest_base . "/" . $post_id;\n \n $new_request = new WP_REST_Request( "GET", $new_route );\n $new_request->set_query_params( $request->get_query_params() );\n $new_request->set_headers( $request->get_headers() );\n \n return $server->dispatch( $new_request );\n }\n }\n }\n \n return $result;\n}, 10, 3 );\n\n// Store UTMs in cookies\nrequire_once get_stylesheet_directory() . '/utm-cookies.php';\n{"version":"1.0","provider_name":"\u042e\u0420\u041a\u041e\u041d\u0421\u0410\u041b\u0422 | \u0410\u0434\u0432\u043e\u043a\u0430\u0442\u0441\u044c\u043a\u0435 \u0431\u044e\u0440\u043e","provider_url":"https:\/\/jurconsult.pro\/ru\/","author_name":"\u0413\u0435\u043d\u043d\u0430\u0434\u0456\u0439 \u041f\u0440\u0430\u0446\u0435\u0432\u0438\u0442\u0438\u0439 | \u0410\u0434\u0432\u043e\u043a\u0430\u0442, \u043a\u0435\u0440\u0443\u044e\u0447\u0438\u0439 \u0431\u044e\u0440\u043e \"\u042e\u0420\u041a\u041e\u041d\u0421\u0410\u041b\u0422\"","author_url":"https:\/\/jurconsult.pro\/ru\/author\/pratsevytyi\/","title":"\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u0447\u0435\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0438\u043a\u0430","type":"rich","width":600,"height":338,"html":"\u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u0447\u0435\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0438\u043a\u0430<\/a><\/blockquote>