Re: genel rss ekleme uygulaması wordpress
Gönderilme zamanı: Çrş Şub 19, 2025 7:18 pm
vergiği cevap cgpt
bu iyi fena değilKod:Tümünü seç
<?php /* Plugin Name: Genel RSS Haber Scraper Description: Excel benzeri tablo üzerinden RSS kaynaklarını ekleyip, RSS haberlerini çekmenize olanak tanır. Ayarlarda; RSS adresi, kategoriler, RSS haber etiket kodu, link eklensin mi, resim HTML kodu ve bağlantı kontrolü yapabilirsiniz. Ayrıca, yazı içeriğinden cümle başları hariç büyük harfli olan ve en çok geçen kelimelerden otomatik 5 etiket oluşturur. Görsel URL’leri için <img src="..."> içindeki .jpg gibi URL’lerde, query string kısmı hariç çekilir. Version: 1.1 Author: Örnek Geliştirici License: GPL2 */ if ( ! defined( 'ABSPATH' ) ) { exit; } class Genel_RSS_Haber_Scraper { private $option_name = 'genel_rss_haber_scraper_sources'; public function __construct() { add_action( 'admin_menu', array( $this, 'add_admin_menu' ) ); add_action( 'admin_init', array( $this, 'register_settings' ) ); add_action( 'wp_ajax_genel_rss_scrape', array( $this, 'handle_scrape_request' ) ); add_action( 'wp_ajax_genel_rss_connection_check', array( $this, 'handle_connection_check' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'frontend_enqueue_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); } public function add_admin_menu() { add_menu_page( 'Genel RSS Haber Scraper', 'RSS Haber Scraper', 'manage_options', 'genel-rss-haber-scraper', array( $this, 'admin_page' ), 'dashicons-rss', 20 ); } public function register_settings() { register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) ); } public function sanitize_options( $options ) { if ( is_array( $options ) ) { foreach ( $options as $key => $source ) { $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0; $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0; $options[$key]['rss_url'] = isset( $source['rss_url'] ) ? esc_url_raw( $source['rss_url'] ) : ''; $options[$key]['categories'] = isset( $source['categories'] ) ? sanitize_text_field( $source['categories'] ) : ''; $options[$key]['tag'] = isset( $source['tag'] ) ? sanitize_text_field( $source['tag'] ) : ''; $options[$key]['image_html'] = isset( $source['image_html'] ) ? wp_kses_post( $source['image_html'] ) : ''; } } return $options; } public function admin_enqueue_scripts( $hook ) { if ( $hook == 'toplevel_page_genel-rss-haber-scraper' ) { wp_enqueue_script( 'genel-rss-admin', plugin_dir_url( __FILE__ ) . 'js/genel-rss-admin.js', array( 'jquery' ), '1.0', true ); wp_localize_script( 'genel-rss-admin', 'genelRssAdmin', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) ); } } public function frontend_enqueue_scripts() { wp_enqueue_script( 'genel-rss-frontend', plugin_dir_url( __FILE__ ) . 'js/genel-rss-frontend.js', array( 'jquery' ), '1.0', true ); wp_localize_script( 'genel-rss-frontend', 'genelRssAjax', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) ); } public function admin_page() { $sources = get_option( $this->option_name, array() ); ?> <div class="wrap"> <h1>Genel RSS Haber Scraper</h1> <form method="post" action="options.php"> <?php settings_fields( 'genel_rss_haber_scraper_options' ); ?> <table class="widefat" id="rss-sources-table"> <thead> <tr> <th>RSS Adresi</th> <th>Kategoriler (virgülle ayrılmış)</th> <th>RSS Haber Etiket</th> <th>Etkin mi?</th> <th>Link Eklensin mi?</th> <th>Resim HTML Kodu</th> <th>Bağlantı Kontrol</th> <th>İşlem</th> </tr> </thead> <tbody> <?php if ( ! empty( $sources ) ) { foreach ( $sources as $index => $source ) { $rss_url = isset( $source['rss_url'] ) ? $source['rss_url'] : ''; $categories = isset( $source['categories'] ) ? $source['categories'] : ''; $tag = isset( $source['tag'] ) ? $source['tag'] : ''; $active = isset( $source['active'] ) ? $source['active'] : 1; $add_link = isset( $source['add_link'] ) ? $source['add_link'] : 0; $image_html = isset( $source['image_html'] ) ? $source['image_html'] : ''; ?> <tr> <td> <input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][rss_url]" value="<?php echo esc_attr( $rss_url ); ?>" size="40" /> </td> <td> <input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][categories]" value="<?php echo esc_attr( $categories ); ?>" size="30" placeholder="Kategori1,Kategori2" /> </td> <td> <input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][tag]" value="<?php echo esc_attr( $tag ); ?>" size="10" placeholder="item veya entry" /> </td> <td> <input type="checkbox" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][active]" value="1" <?php checked( $active, 1 ); ?> /> </td> <td> <input type="checkbox" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][add_link]" value="1" <?php checked( $add_link, 1 ); ?> /> </td> <td> <input type="text" name="<?php echo $this->option_name; ?>[<?php echo $index; ?>][image_html]" value="<?php echo esc_attr( $image_html ); ?>" size="30" placeholder="<img src='...' />" /> </td> <td> <button class="button connection-check" data-row-index="<?php echo $index; ?>">Bağlantıyı Kontrol Et</button> <span class="connection-result" id="conn-result-<?php echo $index; ?>"></span> </td> <td> <button class="button remove-row">Kaldır</button> </td> </tr> <?php } } ?> </tbody> </table> <p> <button type="button" class="button" id="add-row">Yeni Satır Ekle</button> </p> <?php submit_button(); ?> </form> <hr> <h2>Manuel Haber Çekme (Batch Processing)</h2> <p>RSS haberlerini çekmek için aşağıdaki butona tıklayın. İşlem, kaynakları sırayla kontrol eder.</p> <button id="fetch-rss-news" class="button button-primary">Haberleri Çek</button> <div id="rss-news-log" style="margin-top:20px;padding:10px;background:#f9f9f9;border:1px solid #ddd;max-height:300px;overflow-y:auto;"></div> <script> jQuery(document).ready(function($) { var log = $('#rss-news-log'); // Global offset; başlangıçta 0 var currentOffset = 0; // Kayıtlı RSS sayısı (toplam kaynak sayısı) var totalSources = <?php echo count($sources); ?>; $('#fetch-rss-news').on('click', function() { log.html('<p>Haber çekme işlemi başlatıldı...</p>'); processBatch(currentOffset); }); function processBatch(offset) { $.ajax({ url: genelRssAdmin.ajax_url, type: 'POST', data: { action: 'genel_rss_scrape', offset: offset }, success: function(response) { console.log(response); if(response.success) { log.append('<p style="color:green;">' + response.data.message + '</p>'); // İşlem sonrası güncellenen offset değerini alıyoruz currentOffset = response.data.next_offset; // Eğer tüm kaynaklar işlendi ise if ( currentOffset >= totalSources ) { log.append('<p style="font-weight:bold;">Tüm kaynaklar işlendi.</p>'); } } else { log.append('<p style="color:red;">' + response.data.message + '</p>'); } }, error: function() { log.append('<p style="color:red;">Bağlantı hatası!</p>'); } }); } }); </script> </div> <?php } // AJAX: Manuel haber çekme işlemi (batch processing) public function handle_scrape_request() { @set_time_limit(30); ini_set('default_socket_timeout', 15); // Eğer offset POST ile gönderilmişse onu kullan, yoksa veritabanından al (varsayılan 0) $offset = isset($_POST['offset']) ? intval($_POST['offset']) : intval(get_option('genel_rss_last_offset', 0)); $batch_size = 2; $result = $this->fetch_news_batch( $offset, $batch_size ); // Güncel offset değerini veritabanına kaydediyoruz update_option('genel_rss_last_offset', $result['next_offset']); $sources = get_option( $this->option_name, array() ); $totalSources = count($sources); if ( $result['processed'] === 0 && $offset >= $totalSources ) { wp_send_json_success( array( 'message' => 'Tüm kaynaklar işlendi.', 'new_posts' => 0, 'next_offset' => $result['next_offset'], 'total' => $totalSources ) ); } if ( $result['new_posts'] > 0 ) { wp_send_json_success( array( 'message' => $result['new_posts'] . ' yeni haber eklendi.', 'new_posts' => $result['new_posts'], 'next_offset' => $result['next_offset'], 'total' => $totalSources ) ); } else { wp_send_json_success( array( 'message' => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.', 'new_posts' => 0, 'next_offset' => $result['next_offset'], 'total' => $totalSources ) ); } } /** * Belirtilen offset ve batch size’a göre RSS kaynaklarını kontrol eder. * Eğer offset kaynak sayısını aştıysa hiçbir işlem yapılmaz. */ private function fetch_news_batch( $offset, $batch_size ) { $sources = get_option( $this->option_name, array() ); $total = count( $sources ); if ( $offset >= $total ) { return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => $offset ); } $processed = 0; $new_posts = 0; $end = min( $offset + $batch_size, $total ); for ( $i = $offset; $i < $end; $i++ ) { $inserted = $this->process_source( $sources[ $i ] ); $new_posts += $inserted; $processed++; } // İşlenen kaynakların ardından offset’i artırıyoruz. $next_offset = $offset + $batch_size; return array( 'processed' => $processed, 'new_posts' => $new_posts, 'next_offset' => $next_offset ); } /** * Verilen bir RSS kaynağından haber çekmeye çalışır. */ private function process_source( $source ) { if ( empty( $source['active'] ) ) { return 0; } require_once( ABSPATH . 'wp-admin/includes/post.php' ); $rss_url = isset( $source['rss_url'] ) ? trim( $source['rss_url'] ) : ''; $categories_str = isset( $source['categories'] ) ? trim( $source['categories'] ) : ''; $tag = isset( $source['tag'] ) ? trim( $source['tag'] ) : ''; $add_link = isset( $source['add_link'] ) ? $source['add_link'] : 0; $image_html = isset( $source['image_html'] ) ? trim( $source['image_html'] ) : ''; if ( empty( $rss_url ) || empty( $tag ) ) { return 0; } $rss_feed = @simplexml_load_file( $rss_url ); if ( ! $rss_feed ) { error_log( 'RSS yüklenemedi: ' . $rss_url ); return 0; } $inserted = 0; if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) { foreach ( $rss_feed->channel->item as $item ) { $title = (string) $item->title; if ( post_exists( $title ) ) { continue; } $link = (string) $item->link; $description = (string) strip_tags( $item->description ); $content = isset( $item->children( 'content', true )->encoded ) ? (string) strip_tags( $item->children( 'content', true )->encoded ) : ''; $image_url = isset( $item->enclosure['url'] ) ? (string) $item->enclosure['url'] : ''; if ( empty( $image_url ) ) { $combined_text = $description . ' ' . $content; if ( preg_match( '/(https?:\/\/[^\s"\']+\.(?:png|jpg|webp))(\?[^\s"\']*)?/i', $combined_text, $matches ) ) { $image_url = $matches[1]; } } if ( empty( $title ) || ( empty( $content ) && empty( $description ) ) ) { continue; } $post_content = '<p>' . esc_html( $description ) . '</p><p>' . esc_html( $content ) . '</p>'; if ( $add_link ) { $post_content .= '<p><a href="' . esc_url( $link ) . '" target="_blank" rel="noopener noreferrer">Kaynak</a></p>'; } $category_ids = array(); if ( ! empty( $categories_str ) ) { $categories = array_map( 'trim', explode( ',', $categories_str ) ); foreach ( $categories as $cat_name ) { $cat_id = get_cat_ID( $cat_name ); if ( ! $cat_id ) { $cat_id = wp_create_category( $cat_name ); } $category_ids[] = $cat_id; } } $post_id = wp_insert_post( array( 'post_title' => wp_strip_all_tags( $title ), 'post_content' => $post_content, 'post_status' => 'publish', 'post_author' => 1, 'post_category' => $category_ids, 'post_type' => 'post' ) ); if ( ! is_wp_error( $post_id ) ) { if ( ! empty( $image_url ) ) { require_once( ABSPATH . 'wp-admin/includes/media.php' ); require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once( ABSPATH . 'wp-admin/includes/image.php' ); $attachment_id = media_sideload_image( $image_url, $post_id, $title, 'id' ); if ( ! is_wp_error( $attachment_id ) ) { set_post_thumbnail( $post_id, $attachment_id ); } } if ( ! empty( $image_html ) ) { $post_content .= "\n" . $image_html; wp_update_post( array( 'ID' => $post_id, 'post_content' => $post_content ) ); } $tags = $this->extract_tags_from_content( $description . ' ' . $content ); if ( ! empty( $tags ) ) { wp_set_post_tags( $post_id, $tags ); } $inserted++; } } } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) { foreach ( $rss_feed->entry as $entry ) { $title = (string) $entry->title; if ( post_exists( $title ) ) { continue; } $link = ''; if ( isset( $entry->link ) ) { foreach ( $entry->link as $l ) { $attributes = $l->attributes(); if ( isset( $attributes['rel'] ) && (string) $attributes['rel'] === 'alternate' ) { $link = (string) $attributes['href']; break; } } if ( empty( $link ) ) { $link = (string) $entry->link; } } $description = isset( $entry->summary ) ? (string) strip_tags( $entry->summary ) : ''; $content = isset( $entry->content ) ? (string) strip_tags( $entry->content ) : ''; $image_url = ''; if ( empty( $image_url ) ) { $combined_text = $description . ' ' . $content; if ( preg_match( '/(https?:\/\/[^\s"\']+\.(?:png|jpg|webp))(\?[^\s"\']*)?/i', $combined_text, $matches ) ) { $image_url = $matches[1]; } } if ( empty( $title ) || ( empty( $content ) && empty( $description ) ) ) { continue; } $post_content = '<p>' . esc_html( $description ) . '</p><p>' . esc_html( $content ) . '</p>'; if ( $add_link ) { $post_content .= '<p><a href="' . esc_url( $link ) . '" target="_blank" rel="noopener noreferrer">Kaynak</a></p>'; } $category_ids = array(); if ( ! empty( $categories_str ) ) { $categories = array_map( 'trim', explode( ',', $categories_str ) ); foreach ( $categories as $cat_name ) { $cat_id = get_cat_ID( $cat_name ); if ( ! $cat_id ) { $cat_id = wp_create_category( $cat_name ); } $category_ids[] = $cat_id; } } $post_id = wp_insert_post( array( 'post_title' => wp_strip_all_tags( $title ), 'post_content' => $post_content, 'post_status' => 'publish', 'post_author' => 1, 'post_category' => $category_ids, 'post_type' => 'post' ) ); if ( ! is_wp_error( $post_id ) ) { if ( ! empty( $image_url ) ) { require_once( ABSPATH . 'wp-admin/includes/media.php' ); require_once( ABSPATH . 'wp-admin/includes/file.php' ); require_once( ABSPATH . 'wp-admin/includes/image.php' ); $attachment_id = media_sideload_image( $image_url, $post_id, $title, 'id' ); if ( ! is_wp_error( $attachment_id ) ) { set_post_thumbnail( $post_id, $attachment_id ); } } $tags = $this->extract_tags_from_content( $description . ' ' . $content ); if ( ! empty( $tags ) ) { wp_set_post_tags( $post_id, $tags ); } $inserted++; } } } return $inserted; } /** * Yazı içeriğinden cümle başları hariç büyük harfli kelimelerin frekansını hesaplar * ve en çok geçen 5 kelimeyi etiket olarak döndürür. */ private function extract_tags_from_content( $content ) { $sentences = preg_split( '/(?<=[.?!])\s+/', $content, -1, PREG_SPLIT_NO_EMPTY ); $words = array(); foreach ( $sentences as $sentence ) { $sentence_words = preg_split( '/\s+/', $sentence, -1, PREG_SPLIT_NO_EMPTY ); if ( count( $sentence_words ) > 1 ) { for ( $i = 1; $i < count( $sentence_words ); $i++ ) { $words[] = $sentence_words[$i]; } } } $filtered = array(); foreach ( $words as $word ) { $clean = trim( $word, ".,!?()[]{}\"'" ); if ( strlen( $clean ) > 2 && ctype_upper( substr( $clean, 0, 1 ) ) ) { $filtered[] = $clean; } } $freq = array(); foreach ( $filtered as $w ) { $key = strtolower( $w ); if ( isset( $freq[ $key ] ) ) { $freq[ $key ]++; } else { $freq[ $key ] = 1; } } arsort( $freq ); $top_tags = array_slice( array_keys( $freq ), 0, 5 ); return $top_tags; } } new Genel_RSS_Haber_Scraper(); ?>