';
}
}
}, 5);
// Yoast SEO: подменяем title, description, canonical
add_action('wp', function () {
if ($filter_id = get_query_var('wf_filter_id')) {
global $post;
$post = get_post($filter_id);
setup_postdata($post);
add_filter('wpseo_title', fn($title) => get_post_meta($post->ID, '_yoast_wpseo_title', true) ?: $title, 99);
add_filter('wpseo_metadesc', fn($desc) => get_post_meta($post->ID, '_yoast_wpseo_metadesc', true) ?: $desc);
add_filter('wpseo_canonical', fn($can) => get_post_meta($post->ID, '_yoast_wpseo_canonical', true) ?:
home_url($_SERVER['REQUEST_URI']));
wp_reset_postdata();
}
});
/**
* ==================================
* 4. Кастомные хлебны е крошки (breadcrumbs)
* ==================================
*/
function wf_custom_breadcrumbs($crumbs)
{
if (!get_query_var('wf_filter_id')) return $crumbs;
$filter_id = get_query_var('wf_filter_id');
return [
[get_the_title(wc_get_page_id('shop')), get_permalink(wc_get_page_id('shop'))],
[get_the_title($filter_id), home_url($_SERVER['REQUEST_URI'])]
];
}
add_filter('wpseo_breadcrumb_links', 'wf_custom_breadcrumbs');
add _filter('woocommerce_get_breadcrumb', 'wf_custom_breadcrumbs');
/**
* ==================================
* 5. Слова-триггеры в заголовках товаров (the_title)
* ==================================
*/
global $wf_title_processed_ids, $wf_product_title_index;
$wf_title_processed_ids = [];
$wf_product_title_index = 0;
add_action('wp', function () {
global $wf_global_filter_id;
$wf _global_filter_id = get_query_var('wf_filter_id');
});
add_filter('the_title', function ($title, $post_id) {
global $wf_ product_title_index, $wf_title_processed_ids, $wf_global_filter_id;
if (!is_admin() && get_post_type($post_id) === 'product') {
// Для уникальных товаров увеличиваем индекс
if (!in_array($post_id, $wf_title_processed_ids)) {
$wf_title_processed_ids[] = $post_id;
$wf_product_title_index++;
}
$filter_id = $wf_global_filter_id;
$trigger_word = get_post_meta($filter_id, 'wf_trigger_word', true);
$trigger_action = get_post_meta($filter_id, 'wf_trigger_action', true);
$trigger_text = get_post_meta($filter_id, 'wf_trigger_text', true);
$trigger_frequency = max(1, intval(get_post_meta($filter_id, 'wf_trigger_frequency', true)));
if ($wf_product_title_index % $trigger_frequency !== 0 || !$trigger_action || !$trigger_text) {
return $title;
}
$words = explode(' ', $title);
$trigger_found = false;
foreach ($words as $i => $word) {
if (mb_strtolower($word) === mb_strtolower($trigger_word)) {
$trigger_found = true;
switch ($trigger_action) {
case 'before_trigger':
array_splice($words, $i, 0, $trigger_text);
break;
case 'after_trigger':
array_splice($words, $i + 1, 0, $trigger_text);
break;
case 'replace_trigger':
$words[$i] = $trigger_text;
break;
}
break;
}
}
if (!$trigger_found && in_array($trigger_action, ['before_title', 'after_title'])) {
if ($trigger_action === 'before_title') array_unshift($words, $trigger_text);
else array_push($words, $trigger_text);
}
$title = implode(' ', $words);
}
return $title;
}, 10, 2);
/**
* ========================================
* Редирект с зер кал на кастомный URL
* ========================================
*/
add_action('template_redirect', function () {
if (is_admin()) return;
$current_path = rtrim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_P ATH), '/');
$filters = get_posts([
'post_type' => 'filters',
'numberpost s' => -1,
'post_status' => 'publish',
]);
foreach ($filters as $filter) {
$mirrors = get_post_meta($filte r->ID, 'wf_filter_mirrors', true);
if (empty($mirrors) || !is_array($mirrors)) continue;
// Получаем кастомный URL фильтра
$custom_url = get_post_meta( $filter->ID, 'wf_custom_url', true);
if (!$custom_url) continue;
foreach ($mirrors as $mirror) {
$mirror = trim($mirror);
if (empty($mirror) || $mirror === '/') continue;
// Получаем path + query из mirror
$parsed = parse_url($mirr or);
$mirror_path = rtrim($parsed['path'] ?? '', '/');
$mirror_query = $parsed['query'] ?? '';
// Текущий URL
$current_path = rtrim(parse_url($_SERVER['REQ UEST_URI'], PHP_URL_PATH), '/');
$current_query = $_SERVER['QUERY_STRING'] ?? '';
// Сравниваем path и query
if ($mirror_path === $current_pat h && $mirror_query === $current_query) {
wp_redirect(home_url($custom_url), 301);
exit;
}
}
}
}, 5);
/**
* ========================================
* Д обавляем коло нку и фильтрацию в списке в админке
* ========================================
*/
// 1. Добавляем колонки "URL" и "Перейти"
add_filter('manage_filte rs_posts_columns', function($columns) {
$columns['wf_custom_url'] = 'URL';
$columns['wf_custom_url_go'] = 'Перейти';
return $columns;
});
// 2. Выводим данные в колонках
add_action('manage_filters_posts_custom_column', function($column, $post_id) {
if ($column === 'wf_custom_url') {
$url = get_post_meta($post_id, 'wf_custom_url', true);
echo $url ? esc_html($url) : '(нет)';
}
if ($column === 'wf_custom_url_go') {
$url = get_post_meta($post_id, 'wf_custom_url', true);
if ($url) {
echo 'Перейти';
} else {
echo '—';
}
}
}, 10, 2);
// 3. Поиск по URL (и по названию фильтра)
add_filter('posts_search', function($search, $query) {
global $wpdb;
if (!is_admin() || !$query->is_main_query() || $query->get('post_type') !== 'filters') {
return $search;
}
$search_term = $query->get('s');
if ($search_term) {
$search = '';
$search .= " AND (";
$search .= "{$wpdb->posts}.post_title LIKE '%" . esc_sql($search_term) . "%'";
$search .= " OR EXISTS (SELECT 1 FROM {$wpdb->postmeta} WHERE post_id = {$wpdb->posts}.ID AND meta_key = 'wf_custom_url'
AND meta_value LIKE '%" . esc_sql($search_term) . "%')";
$search .= ")";
}
return $search;
}, 10, 2);
// 4. Сортировка
add_filter('manage_edit-filters_sortable_columns', function($columns) {
$columns['wf_custom_url'] = 'wf_custom_url';
return $columns;
});
/**
* ========================================
* Запрет на пере ход по прямому URL
* ========================================
*/
add_action('template_redirect', function () {
if (is_singular('filters')) {
// Проверяем, не находимся ли мы на кастомном URL (например, твой обработчик уже вывел контент)
// Если стандартная страница фильтра — выдаём 404
global $post;
// Например, если мы не на своем кастомном URL (логика ниже подправляется под твой роутинг)
// По умолчанию ВСЕ страницы CPT filters становятся 404!
if (!defined('WF_CUSTOM_FILTER_PAGE')) { // Можешь определить константу при выводе кастомного урла
global $wp_query;
$wp_query->set_404();
status_header(404);
nocache_headers();
include(get_query_template('404'));
exit;
}
}
// Запрет на архив фильтров (если вдруг кто-то туда попадет)
if (is_post_type_archive('filters')) {
global $wp_query;
$wp_query->set_404();
status_header(404);
nocache_headers();
include(get_query_template('404'));
exit;
}
});
/**
* ========================================
* 6. Yoast SEO s itemap: подмена URL на кастомные
* ========================================
* Меняем ссылки в sitemap на значения из мета `wf_custom_url`
* для любых постов/терминов, если мета задана.
* Регистрируем хуки ПОСЛЕ загрузки Yoast.
*/
if (!function_exists('wf_register_yoast_sitemap_overrides')) {
function wf_register_yoast_sitemap_overrides() {
static $done = false;
if ($done) { return; }
$done = true;
// Хелпер: абсолютный URL из wf_custom_url (post/term)
$wf_get _custom_abs_url = function ($entity) {
$raw = '';
if ($entity instanceof WP_Post) {
$raw = get_post_meta($entity->ID, 'wf_custom_url', true);
} elseif ($entity instanceof WP_Term) {
$raw = get_term_meta($entity->term_id, 'wf_custom_url', true);
}
$raw = is_string($raw) ? trim($raw) : '';
if ($raw === '') return null;
// Абсолютный? — вернём как есть (без дубля завершающего слэша)
if (filter_var($raw, FILTER_VALIDATE_URL)) {
return rtrim($raw, '/');
}
// Относительный путь → соберём абсолютный
$path = '/' . ltr im($raw, '/');
return rtrim(home_url($path), '/');
};
// Новый API Yoast: любая запись sitemap (post/term)
add_filte r('wpseo_sitemap_entry', function ($url, $type, $obj) use ($wf_get_custom_abs_url) {
$custom = $wf_get_custom_abs_url($obj);
if ($custom) {
// Не навязываем слэш к URL с query/fragment
$url['loc'] = strpos($custom, '?') === false && strpos($custom, '#') === false
? trailingslashit($custom)
: $custom;
}
return $url;
}, 10, 3);
// Старый API Yoast: постовые URL
add_filter('wpseo_xml_sitema p_post_url', function ($permalink, $post) use ($wf_get_custom_abs_url) {
$custom = $wf_get_custom_abs_url($post);
if (!$custom) return $permalink;
return strpos($custom, '?') === false && strpos($custom, '#') === false
? trailingslashit($custom)
: $custom;
}, 10, 2);
// Сброс кэша sitemap при изменении wf_custom_url
add_action(' save_post', function ($post_id) {
if (wp_is_post_revision($post_id)) return;
$val = get_post_meta($post_id, 'wf_custom_url', true);
if ($val !== '' && $val !== null) {
do_action('wpseo_invalidate_sitemap_cache');
}
});
add_action('edited_term', function ($term_id) {
$val = get_term_meta($term_id, 'wf_custom_url', true);
if ($val !== '' && $val !== null) {
do_action('wpseo_invalidate_sitemap_cache');
}
});
}
// 1) Идеально — когда Yoast сообщает, что загрузился
add_action ('wpseo_loaded', 'wf_register_yoast_sitemap_overrides');
// 2) Подстраховка: если Yoast уже загружен к init — тоже регистри руем
add_action('init', function () {
if (defined('WPSEO_VERSION')) {
wf_register_yoast_sitemap_overrides();
}
}, 20);
}
Fatal error: Uncaught Error: Class 'WF_Rewrite' not found in /var/www/kompasgid.ru/wp-content/plugins/woocommerce-filters/woocommerce-filters.php on line 33