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 .= "