filename_fallback = trailingslashit($upload_dir['basedir']) . 'rsswire/rss.xml'; register_activation_hook(__FILE__, [$this, 'on_activate']); add_action('init', [$this, 'add_rewrite']); add_action('template_redirect', [$this, 'serve_rss']); add_action('save_post', [$this, 'on_post_change'], 10, 3); add_action('trash_post', [$this, 'on_post_change']); add_action('untrash_post', [$this, 'on_post_change']); add_action('deleted_post', [$this, 'on_post_change']); add_action('publish_post', [$this, 'on_post_change']); add_action('admin_menu', [$this, 'add_admin_menu']); add_action('admin_post_rsswire_regenerate', [$this, 'handle_regenerate_action']); } public function on_activate() { add_option($this->option_auto, 1); $this->maybe_create_directory(); $this->generate_and_write(false); $this->add_rewrite(); flush_rewrite_rules(); } private function maybe_create_directory() { $dir = dirname($this->filename_fallback); if (!file_exists($dir)) { wp_mkdir_p($dir); } } public function add_rewrite() { add_rewrite_rule('^rss\.xml$', 'index.php?rsswire=1', 'top'); add_rewrite_tag('%rsswire%', '1'); } public function serve_rss() { if (get_query_var('rsswire')) { if (file_exists($this->filename_fallback)) { header('Content-Type: application/rss+xml; charset=UTF-8'); readfile($this->filename_fallback); exit; } } } public function on_post_change($post_id = 0, $post = null) { if (!get_option($this->option_auto)) return; if (!$post) { $post = get_post($post_id); } if (!$post || $post->post_type !== 'post' || $post->post_status !== 'publish') { return; } $this->generate_and_write(false); } private function generate_and_write($fetch_all = false) { $rss = $this->generate_rss($fetch_all); if (!$rss) return false; $this->maybe_create_directory(); $this->write_file($this->filename_fallback, $rss); return $this->filename_fallback; } private function write_file($path, $contents) { $tmp = $path . '.tmp'; if (file_put_contents($tmp, $contents) === false) { return false; } rename($tmp, $path); chmod($path, 0644); return true; } private function escape_xml($text) { return htmlspecialchars($text, ENT_XML1 | ENT_COMPAT, 'UTF-8'); } private function generate_rss($fetch_all = false) { $posts = get_posts([ 'post_type' => 'post', 'post_status' => 'publish', 'orderby' => 'date', 'order' => 'DESC', 'posts_per_page' => $fetch_all ? -1 : 100 ]); if (!$posts) return ''; $xml = "\n"; $xml .= "\n"; $xml .= "{$this->escape_xml(get_bloginfo('name'))}\n"; $xml .= "{$this->escape_xml(get_bloginfo('url'))}\n"; $xml .= "{$this->escape_xml(get_bloginfo('description'))}\n"; foreach ($posts as $p) { $content = apply_filters('the_content', $p->post_content); $xml .= "\n"; $xml .= "{$this->escape_xml($p->post_title)}\n"; $xml .= "{$this->escape_xml(get_permalink($p))}\n"; $xml .= "" . get_post_time('r', true, $p) . "\n"; foreach (get_the_category($p->ID) as $cat) { $xml .= "{$this->escape_xml($cat->name)}\n"; } $xml .= "\n"; $xml .= "\n"; } return $xml . ""; } public function add_admin_menu() { add_menu_page('RSSWire', 'RSSWire', 'manage_options', 'rsswire', [$this, 'admin_page'], 'dashicons-rss', 80); } public function admin_page() { $auto = get_option($this->option_auto); $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : ''; ?>

RSSWire

RSS regenerated successfully.

Filesystem path: filename_fallback); ?>

Public URL:

option_auto, isset($_POST['rsswire_auto'])); $this->generate_and_write(false); $url = add_query_arg( array( 'rsswire_done' => '1', '_wpnonce' => wp_create_nonce('rsswire_done_action'), ), admin_url('admin.php?page=rsswire') ); wp_safe_redirect($url); exit; } } new RSSWire();