271 lines
10 KiB
PHP
271 lines
10 KiB
PHP
|
|
<?php
|
|||
|
|
/**
|
|||
|
|
* Custom RSS Feed for profile_article posts
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
// Защита от прямого доступа
|
|||
|
|
if (!defined('ABSPATH')) {
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class CustomProfileArticleRSS {
|
|||
|
|
|
|||
|
|
public function __construct() {
|
|||
|
|
add_action('init', [$this, 'add_rss_endpoint']);
|
|||
|
|
add_action('template_redirect', [$this, 'generate_rss_feed']);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Добавляем endpoint для RSS ленты
|
|||
|
|
*/
|
|||
|
|
public function add_rss_endpoint() {
|
|||
|
|
add_rewrite_rule(
|
|||
|
|
'^rss-feed/?$',
|
|||
|
|
'index.php?custom_rss_feed=1',
|
|||
|
|
'top'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
add_rewrite_tag('%custom_rss_feed%', '([^&]+)');
|
|||
|
|
add_rewrite_tag('%rss_date%', '([^&]+)');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Генерируем RSS ленту
|
|||
|
|
*/
|
|||
|
|
public function generate_rss_feed() {
|
|||
|
|
if (get_query_var('custom_rss_feed') || isset($_GET['rss-feed'])) {
|
|||
|
|
$date = isset($_GET['date']) ? sanitize_text_field($_GET['date']) : date('Y-m-d');
|
|||
|
|
|
|||
|
|
// Валидация даты
|
|||
|
|
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
|
|||
|
|
$date = date('Y-m-d');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$this->output_rss_feed($date);
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Получаем URL иконки сайта
|
|||
|
|
*/
|
|||
|
|
private function get_site_icon_url() {
|
|||
|
|
$site_icon_id = get_option('site_icon');
|
|||
|
|
if ($site_icon_id) {
|
|||
|
|
return wp_get_attachment_image_url($site_icon_id, 'full');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Fallback на логотип или дефолтную иконку
|
|||
|
|
$custom_logo_id = get_theme_mod('custom_logo');
|
|||
|
|
if ($custom_logo_id) {
|
|||
|
|
return wp_get_attachment_image_url($custom_logo_id, 'full');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return home_url('/wp-admin/images/wordpress-logo.png');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private function get_clean_post_content($post) {
|
|||
|
|
|
|||
|
|
$content = apply_filters('the_content', $post->post_content);
|
|||
|
|
|
|||
|
|
// Удаляем запрещенные для Турбо элементы
|
|||
|
|
$content = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<style\b[^>]*>.*?<\/style>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<iframe\b[^>]*>.*?<\/iframe>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<form\b[^>]*>.*?<\/form>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<input[^>]*>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<button[^>]*>.*?<\/button>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<select[^>]*>.*?<\/select>/is', '', $content);
|
|||
|
|
$content = preg_replace('/<textarea[^>]*>.*?<\/textarea>/is', '', $content);
|
|||
|
|
$content = str_replace('<p></p>', '', $content);
|
|||
|
|
|
|||
|
|
// Удаляем определенные классы
|
|||
|
|
$content = preg_replace('/<div[^>]*class="[^"]*(ads|advert|banner|social|share|widget|comments)[^"]*"[^>]*>.*?<\/div>/is', '', $content);
|
|||
|
|
|
|||
|
|
// Разрешаем только турбо-совместимые теги
|
|||
|
|
$allowed_tags = [
|
|||
|
|
'p' => ['class' => [], 'style' => []],
|
|||
|
|
'br' => [],
|
|||
|
|
'strong' => [],
|
|||
|
|
'em' => [],
|
|||
|
|
'b' => [],
|
|||
|
|
'i' => [],
|
|||
|
|
'ul' => [],
|
|||
|
|
'ol' => [],
|
|||
|
|
'li' => [],
|
|||
|
|
'h1' => [],
|
|||
|
|
'h2' => [],
|
|||
|
|
'h3' => [],
|
|||
|
|
'h4' => [],
|
|||
|
|
'h5' => [],
|
|||
|
|
'h6' => [],
|
|||
|
|
'a' => ['href' => [], 'title' => []],
|
|||
|
|
'img' => ['src' => [], 'alt' => [], 'title' => [], 'width' => [], 'height' => []],
|
|||
|
|
'blockquote' => [],
|
|||
|
|
'figure' => [],
|
|||
|
|
'header' => [],
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
$content = wp_kses($content, $allowed_tags);
|
|||
|
|
|
|||
|
|
return $content;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Формируем XML ленту
|
|||
|
|
*/
|
|||
|
|
private function output_rss_feed($date) {
|
|||
|
|
global $wpdb;
|
|||
|
|
|
|||
|
|
// Определяем диапазон дат: 7 дней до указанной даты
|
|||
|
|
$end_date = $date; // указанная дата
|
|||
|
|
$start_date = date('Y-m-d', strtotime($date . ' -6 days')); // 7 дней назад (включая указанную дату)
|
|||
|
|
|
|||
|
|
//такая лента формируется на каждую дату и содержит все статьи за 7 дней до указанной даты
|
|||
|
|
$posts = $wpdb->get_results($wpdb->prepare("
|
|||
|
|
SELECT *
|
|||
|
|
FROM {$wpdb->posts}
|
|||
|
|
WHERE post_type = 'profile_article'
|
|||
|
|
AND post_status = 'publish'
|
|||
|
|
AND DATE(post_date) BETWEEN %s AND %s
|
|||
|
|
AND post_password = ''
|
|||
|
|
AND ID NOT IN (
|
|||
|
|
SELECT post_id
|
|||
|
|
FROM {$wpdb->postmeta}
|
|||
|
|
WHERE meta_key IN ('_no_aeroflot', '_is_advertisement', '_only_link_access', '_hide_on_website', '_hide_on_mainpage')
|
|||
|
|
AND meta_value = '1'
|
|||
|
|
)
|
|||
|
|
ORDER BY post_date DESC
|
|||
|
|
", $start_date, $end_date));
|
|||
|
|
|
|||
|
|
// Конвертируем в объекты WP_Post
|
|||
|
|
$posts = array_map(function($post) {
|
|||
|
|
return new WP_Post($post);
|
|||
|
|
}, $posts);
|
|||
|
|
|
|||
|
|
// Устанавливаем заголовки
|
|||
|
|
header('Content-Type: application/rss+xml; charset=' . get_option('blog_charset'), true);
|
|||
|
|
|
|||
|
|
// Начинаем вывод XML
|
|||
|
|
echo '<?xml version="1.0" encoding="' . get_option('blog_charset') . '"?>';
|
|||
|
|
?>
|
|||
|
|
<rss version="2.0"
|
|||
|
|
xmlns:yandex="http://news.yandex.ru"
|
|||
|
|
xmlns:media="http://search.yahoo.com/mrss/"
|
|||
|
|
xmlns:turbo="http://turbo.yandex.ru">
|
|||
|
|
|
|||
|
|
<channel>
|
|||
|
|
<title><?php echo esc_xml(get_bloginfo('name')); ?></title>
|
|||
|
|
<link><?php echo esc_url(home_url()); ?></link>
|
|||
|
|
<description><?php echo esc_xml(get_bloginfo('description')); ?></description>
|
|||
|
|
<language><?php echo esc_xml(get_bloginfo('language')); ?></language>
|
|||
|
|
<lastBuildDate><?php echo esc_xml(gmdate(DATE_RSS)); ?></lastBuildDate>
|
|||
|
|
<pubDate><?php echo esc_xml(gmdate(DATE_RSS)); ?></pubDate>
|
|||
|
|
<guid>https://profile.ru</guid>
|
|||
|
|
<generator>Информационное агенство Деловой журнал Профиль</generator>
|
|||
|
|
<image>
|
|||
|
|
<url><?php echo esc_url($this->get_site_icon_url()); ?></url>
|
|||
|
|
<title><?php echo esc_xml(get_bloginfo('name')); ?></title>
|
|||
|
|
<link><?php echo esc_url(home_url()); ?></link>
|
|||
|
|
</image>
|
|||
|
|
<?php if (empty($posts)): ?>
|
|||
|
|
<item>
|
|||
|
|
<title>No posts for period <?php echo esc_xml($start_date); ?> to <?php echo esc_xml($end_date); ?></title>
|
|||
|
|
<link><?php echo esc_url(home_url()); ?></link>
|
|||
|
|
<description>No posts found for this period</description>
|
|||
|
|
<pubDate><?php echo esc_xml(gmdate(DATE_RSS)); ?></pubDate>
|
|||
|
|
<guid isPermaLink="false">no-posts-<?php echo esc_xml($start_date . '-to-' . $end_date); ?></guid>
|
|||
|
|
</item>
|
|||
|
|
<?php else: ?>
|
|||
|
|
<?php foreach ($posts as $post):
|
|||
|
|
$post = new WP_Post($post);
|
|||
|
|
$post_url = get_permalink($post->ID);
|
|||
|
|
$post_date = gmdate(DATE_RSS, strtotime($post->post_date_gmt));
|
|||
|
|
$excerpt = get_the_excerpt($post->ID);
|
|||
|
|
$content = $this->get_clean_post_content($post);
|
|||
|
|
$thumbnail = get_the_post_thumbnail_url($post->ID, 'large');
|
|||
|
|
// Получаем авторов из плагина Co-Authors
|
|||
|
|
$authors = get_coauthors($post->ID);
|
|||
|
|
?>
|
|||
|
|
<item>
|
|||
|
|
<title><?php echo esc_xml(get_the_title($post->ID)); ?></title>
|
|||
|
|
<link><?php echo esc_url($post_url); ?></link>
|
|||
|
|
<description><?php echo esc_xml($excerpt); ?></description>
|
|||
|
|
<pubDate><?php echo esc_xml($post_date); ?></pubDate>
|
|||
|
|
<?php if (!empty($authors)): ?>
|
|||
|
|
<?php
|
|||
|
|
$author_names = array();
|
|||
|
|
foreach ($authors as $author) {
|
|||
|
|
$author_names[] = $author->display_name;
|
|||
|
|
}
|
|||
|
|
?>
|
|||
|
|
<author><?php echo esc_xml(implode(', ', $author_names)); ?></author>
|
|||
|
|
<?php else: ?>
|
|||
|
|
<?php $default_author = get_the_author_meta('display_name', $post->post_author); ?>
|
|||
|
|
<author><?php echo esc_xml($default_author); ?></author>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
<guid><?php echo esc_url($post_url); ?></guid>
|
|||
|
|
<?php if ($thumbnail): ?>
|
|||
|
|
<imageAnnounce>
|
|||
|
|
<url><?php echo esc_url($thumbnail); ?></url>
|
|||
|
|
<title><?php echo esc_xml(get_the_title($post->ID)); ?></title>
|
|||
|
|
<description><?php echo esc_xml($excerpt); ?></description>
|
|||
|
|
</imageAnnounce>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
<?php if ($thumbnail): ?>
|
|||
|
|
<image>
|
|||
|
|
<url><?php echo esc_url($thumbnail); ?></url>
|
|||
|
|
<title><?php echo esc_xml(get_the_title($post->ID)); ?></title>
|
|||
|
|
<description><?php echo esc_xml($excerpt); ?></description>
|
|||
|
|
<link><?php echo esc_url($post_url); ?></link>
|
|||
|
|
</image>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
<?php
|
|||
|
|
$categories = get_the_category($post->ID);
|
|||
|
|
foreach ($categories as $category) {
|
|||
|
|
echo '<category>' . esc_xml($category->name) . '</category>';
|
|||
|
|
}
|
|||
|
|
?>
|
|||
|
|
<content:encoded>
|
|||
|
|
<![CDATA[<?php echo $content; ?>]]>
|
|||
|
|
</content:encoded>
|
|||
|
|
</item>
|
|||
|
|
<?php endforeach; ?>
|
|||
|
|
<?php endif; ?>
|
|||
|
|
|
|||
|
|
</channel>
|
|||
|
|
</rss>
|
|||
|
|
<?php
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Получаем контент поста
|
|||
|
|
*/
|
|||
|
|
private function get_post_content($post) {
|
|||
|
|
$content = apply_filters('the_content', $post->post_content);
|
|||
|
|
$content = str_replace(']]>', ']]>', $content);
|
|||
|
|
return $content;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Активация - сбрасываем rewrite rules
|
|||
|
|
*/
|
|||
|
|
public static function activate() {
|
|||
|
|
flush_rewrite_rules();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Деактивация - чистим rewrite rules
|
|||
|
|
*/
|
|||
|
|
public static function deactivate() {
|
|||
|
|
flush_rewrite_rules();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Инициализация
|
|||
|
|
new CustomProfileArticleRSS();
|
|||
|
|
|
|||
|
|
// Хуки активации/деактивации
|
|||
|
|
register_activation_hook(__FILE__, ['CustomProfileArticleRSS', 'activate']);
|
|||
|
|
register_deactivation_hook(__FILE__, ['CustomProfileArticleRSS', 'deactivate']);
|