3. sayfa (Toplam 4 sayfa)

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Sal Şub 18, 2025 4:48 pm
gönderen muratca61
bu uygulamada döngüde bir sorun var. rss admin ayarlarını yaptıktan sonra bir kaç haber çektikten sonra daha çekim yapmıyor bunu bir kontrol eder misin.
Aşağıdaki örnekte, RSS kaynaklarınızı her seferinde (bütün döngüyü) kontrol edecek şekilde batch (parça) mantığını güncelliyoruz. Böylece, örneğin tek bir kaynak varsa veya kaynak sayınız azsa, döngü sonunda offset null yerine 0’ye (yani tekrar en başa) ayarlanıyor. Ayrıca, JavaScript tarafında da; eğer bir döngüde hiç yeni haber eklenmezse döngü sonlanıyor, aksi halde yine kaynaklar kontrol ediliyor.

Aşağıdaki kodu inceleyebilirsiniz:

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();
Açıklamalar
Batch İşlemi (fetch_news_batch) Güncellemesi:

Döngü sonunda, eğer offset + batch_size toplam kaynak sayısına ulaşırsa, offset sıfırlanıyor (yani next_offset = 0). Böylece; örneğin sadece 1 veya 2 kaynağınız varsa, döngüde bir kere tamamlandıktan sonra sonraki AJAX çağrısı yeniden tüm kaynakları kontrol eder.
JavaScript Tarafı:

Döngü her seferinde gelen next_offset değeriyle devam eder.
Eğer döngüde hiç yeni haber eklenmezse (new_posts 0 ise) döngü sonlanır. Böylece gereksiz AJAX çağrıları yapılmaz.
Bu güncellemelerle, ayarlar yapıldıktan ve birkaç haber çekildikten sonra da (örneğin, tek bir kaynak varsa) sistem her seferinde tüm kaynakları yeniden kontrol edecek ve eğer gerçekten yeni haber varsa ekleyecektir.

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 5:52 am
gönderen muratca61
yeni ress eklediğimde son rss kaydının üzerine yazıyor

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 5:56 am
gönderen muratca61
muratca61 yazdı: Çrş Şub 19, 2025 5:52 am
yeni ress eklediğimde son rss kaydının üzerine yazıyor

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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($) {

                // Yeni satır ekleme işlemi (benzersiz index ile)
                $('#add-row').on('click', function(e) {
                    e.preventDefault();
                    // Mevcut satır sayısını alarak yeni index oluşturuyoruz
                    var newIndex = $('#rss-sources-table tbody tr').length;
                    
                    var newRow = '<tr>' +
                        '<td><input type="text" name="<?php echo $this->option_name; ?>['+newIndex+'][rss_url]" value="" size="40" /></td>' +
                        '<td><input type="text" name="<?php echo $this->option_name; ?>['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
                        '<td><input type="text" name="<?php echo $this->option_name; ?>['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
                        '<td><input type="checkbox" name="<?php echo $this->option_name; ?>['+newIndex+'][active]" value="1" /></td>' +
                        '<td><input type="checkbox" name="<?php echo $this->option_name; ?>['+newIndex+'][add_link]" value="1" /></td>' +
                        '<td><input type="text" name="<?php echo $this->option_name; ?>['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
                        '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
                        '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
                        '<td><button class="button remove-row">Kaldır</button></td>' +
                    '</tr>';
                    $('#rss-sources-table tbody').append(newRow);
                });

                // Satır kaldırma işlemi
                $('#rss-sources-table').on('click', '.remove-row', function(e) {
                    e.preventDefault();
                    $(this).closest('tr').remove();
                });

                // Bağlantı kontrolü butonu
                $('#rss-sources-table').on('click', '.connection-check', function(e) {
                    e.preventDefault();
                    var rowIndex = $(this).data('row-index');
                    var row = $(this).closest('tr');
                    var rss_url = row.find('input[name*="[rss_url]"]').val();
                    var tag = row.find('input[name*="[tag]"]').val();
                    var resultSpan = $('#conn-result-' + rowIndex);
                    resultSpan.html('Kontrol ediliyor...');
                    $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {
                            action: 'genel_rss_connection_check',
                            rss_url: rss_url,
                            tag: tag
                        },
                        success: function(response) {
                            if (response.success) {
                                resultSpan.html('<span style="color:green;">' + response.data.message + '</span>');
                            } else {
                                resultSpan.html('<span style="color:red;">' + response.data.message + '</span>');
                            }
                        },
                        error: function() {
                            resultSpan.html('<span style="color:red;">Bağlantı hatası!</span>');
                        }
                    });
                });

                // Manuel haber çekme (batch processing)
                var log = $('#rss-news-log');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 5:58 am
gönderen muratca61
bunda değişiklik yapmalımıyım

Kod:Tümünü seç

genel-rss-admin.js

Kod:Tümünü seç

jQuery(document).ready(function($) {
    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var index = $('#rss-sources-table tbody tr').length;
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+index+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+index+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+index+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 5:59 am
gönderen muratca61
muratca61 yazdı: Çrş Şub 19, 2025 5:58 am
bunda değişiklik yapmalımıyım

Kod:Tümünü seç

genel-rss-admin.js

Kod:Tümünü seç

jQuery(document).ready(function($) {
    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var index = $('#rss-sources-table tbody tr').length;
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+index+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+index+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+index+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});
Evet, eğer yeni satırların index’ini dinamik oluşturmak ve form alanlarını güncel eklenti koduyla uyumlu hale getirmek istiyorsanız, genel-rss-admin.js dosyasında da değişiklik yapmanız gerekecektir.

Örneğin, eklenti dosyasında eklediğimiz satırda "active" checkbox’ı da bulunuyor. Eğer bu alanı da kullanacaksanız, JS dosyanızdaki satır oluşturma kodunu aşağıdaki gibi güncelleyebilirsiniz:

Kod:Tümünü seç

jQuery(document).ready(function($) {
    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var index = $('#rss-sources-table tbody tr').length;
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            // "active" alanı ekleniyor
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+index+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+index+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+index+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+index+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+index+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 6:05 am
gönderen muratca61
Aşağıda,

Kod:Tümünü seç

genel-rss-admin.js
dosyanızda yapmanız gereken güncellemeyi bulabilirsiniz:

Kod:Tümünü seç

jQuery(document).ready(function($) {
    // Sayfada mevcut satır sayısını alıp global sayaç olarak tanımlıyoruz.
    var newIndex = $('#rss-sources-table tbody tr').length; 

    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            // "active" alanı eklendi (varsa)
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
        newIndex++; // Global sayacı bir artırıyoruz
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 6:28 am
gönderen muratca61
deepseek sorduk. cgpt yapamadı

Kod:Tümünü seç

aşağıdaki kod yeni rss eklediğimde yeni rss kaydı yapmıyor kayıtlı olan son rss üzerine yazıyor  

Kod:Tümünü seç

genel-rss-haber-scraper.php

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();
/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/js

Kod:Tümünü seç

genel-rss-admin.js

Kod:Tümünü seç

jQuery(document).ready(function($) {
    // Global sayaç: Sayfa yüklendiğinde mevcut satırlardan bağımsız benzersiz index değeri
    var newIndex = $('#rss-sources-table tbody tr').length; 

    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
        newIndex++; // Her eklemede global sayaç bir artırılır
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});
yukarısının tümü

Kod:Tümünü seç

aşağıdaki kod yeni rss eklediğimde yeni rss kaydı yapmıyor kayıtlı olan son rss üzerine yazıyor  genel-rss-haber-scraper.php
<?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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();
/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/js
genel-rss-admin.js
jQuery(document).ready(function($) {
    // Global sayaç: Sayfa yüklendiğinde mevcut satırlardan bağımsız benzersiz index değeri
    var newIndex = $('#rss-sources-table tbody tr').length; 

    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
        newIndex++; // Her eklemede global sayaç bir artırılır
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
});    

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 6:54 am
gönderen muratca61
pek umut yok ama copilota sorduk

Kod:Tümünü seç

selam yeni rss ekleyince son rss kaydının üzerine yazıyor sanki maksimum 5 rss yapılabilir gibi davranış gösteriyor genel-rss-admin.js kodu:
jQuery(document).ready(function($) {
    // Mevcut satırlardaki maksimum indeksi bul
    var indexes = [];
    $('#rss-sources-table tbody tr').each(function() {
        var inputName = $(this).find('input[name^="genel_rss_haber_scraper_sources["]').first().attr('name');
        var matches = inputName.match(/\[(\d+)\]/);
        if (matches) {
            indexes.push(parseInt(matches[1], 10));
        }
    });
    var newIndex = indexes.length ? Math.max(...indexes) + 1 : 0;

    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
        newIndex++; // Her eklemede global sayaç bir artırılır
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü (değişmedi)
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
}); 

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 6:57 am
gönderen muratca61
muratca61 yazdı: Çrş Şub 19, 2025 6:54 am
pek umut yok ama copilota sorduk

Kod:Tümünü seç

selam yeni rss ekleyince son rss kaydının üzerine yazıyor sanki maksimum 5 rss yapılabilir gibi davranış gösteriyor genel-rss-admin.js kodu:
jQuery(document).ready(function($) {
    // Mevcut satırlardaki maksimum indeksi bul
    var indexes = [];
    $('#rss-sources-table tbody tr').each(function() {
        var inputName = $(this).find('input[name^="genel_rss_haber_scraper_sources["]').first().attr('name');
        var matches = inputName.match(/\[(\d+)\]/);
        if (matches) {
            indexes.push(parseInt(matches[1], 10));
        }
    });
    var newIndex = indexes.length ? Math.max(...indexes) + 1 : 0;

    // Yeni satır ekleme
    $('#add-row').on('click', function(e) {
        e.preventDefault();
        var row = '<tr>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][rss_url]" value="" size="40" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][categories]" value="" size="30" placeholder="Kategori1,Kategori2" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][tag]" value="" size="10" placeholder="item veya entry" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][active]" value="1" /></td>' +
            '<td><input type="checkbox" name="genel_rss_haber_scraper_sources['+newIndex+'][add_link]" value="1" /></td>' +
            '<td><input type="text" name="genel_rss_haber_scraper_sources['+newIndex+'][image_html]" value="" size="30" placeholder="<img src=\'...\' />" /></td>' +
            '<td><button class="button connection-check" data-row-index="'+newIndex+'">Bağlantıyı Kontrol Et</button>' +
            '<span class="connection-result" id="conn-result-'+newIndex+'"></span></td>' +
            '<td><button class="button remove-row">Kaldır</button></td>' +
            '</tr>';
        $('#rss-sources-table tbody').append(row);
        newIndex++; // Her eklemede global sayaç bir artırılır
    });

    // Satır silme
    $('#rss-sources-table').on('click', '.remove-row', function(e) {
        e.preventDefault();
        $(this).closest('tr').remove();
    });

    // Bağlantı kontrolü (değişmedi)
    $('#rss-sources-table').on('click', '.connection-check', function(e) {
        e.preventDefault();
        var rowIndex = $(this).data('row-index');
        var row = $(this).closest('tr');
        var rss_url = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[rss_url]"]').val();
        var tag = row.find('input[name^="genel_rss_haber_scraper_sources"]').filter('[name*="[tag]"]').val();
        var resultSpan = $('#conn-result-' + rowIndex);
        resultSpan.text('Kontrol ediliyor...');
        $.ajax({
            url: genelRssAdmin.ajax_url,
            type: 'POST',
            data: {
                action: 'genel_rss_connection_check',
                rss_url: rss_url,
                tag: tag
            },
            success: function(response) {
                if(response.success) {
                    resultSpan.text(response.data.message).css('color', 'green');
                } else {
                    resultSpan.text(response.data.message).css('color', 'red');
                }
            },
            error: function() {
                resultSpan.text('Bağlantı hatası!').css('color', 'red');
            }
        });
    });
}); 
Merhaba! Kodunuzu inceledim. Görünüşe göre newIndex değeri her yeni satır eklediğinizde sadece 1 artırılıyor ve önceden eklenen satırlarla birlikte her zaman benzersiz bir indeks oluşturuyor. Bu nedenle, maksimum sayıda RSS kaynağı eklemek için bir sınırlama bulunmuyor. Ancak, bazı tarayıcı ve JavaScript sınırlamaları nedeniyle tablo düzeninde görünür olan satır sayısı veya bellekte taşınabilir olan veri miktarı kısıtlamalar olabilir.

Sisteminizde maksimum 5 RSS kaynağı görünüyor gibi davranmasının olası birkaç sebebi olabilir:

Veritabanı veya sunucu tarafı sınırlamaları: Veritabanında veya sunucunuzda maksimum RSS kaynağı sayısı ile ilgili bir sınırlama olabilir.

[*]Tarayıcı belleği sınırı: Tarayıcı belleği, özellikle büyük veri miktarlarıyla çalışırken veya sürekli veri eklerken sınırlandırılabilir.

CSS/Dizayn sınırlamaları: CSS veya sayfa düzeniniz tablodaki satır sayısında kısıtlamalar getirebilir.

Kodunuzu kontrol etmek için, her ekleme ve silme işleminden sonra newIndex değerini güncellediğinizden emin olmalısınız. Ayrıca, belleği veya tarayıcı belleğini kontrol etmek için geliştirme araçlarını kullanabilirsiniz.

Bu konuda daha spesifik bir sorunuz varsa veya başka bir yardıma ihtiyacınız olursa lütfen bana bildirin! 🌟

Re: genel rss ekleme uygulaması wordpress

Gönderilme zamanı: Çrş Şub 19, 2025 7:05 pm
gönderen muratca61
cgpt sorduk

Kod:Tümünü seç

bu kodda sorun var. eklenen tün rss ler sanki kontrol edilmiyor. yani her tıklamada/sorgulamada/tetiklemede kayıtlı rss leri ilk sıradan başlıyor bu durumda sürekli güncellenen rss den öteye gidemiyor. her tıklanmada en son rss den sonrakini sorgulaması gerekiyor. ilgilenir misin

Kod:Tümünü seç

genel-rss-haber-scraper.php
dosya yığını

Kod:Tümünü seç

/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/genel-rss-haber-scraper.php
/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/js/genel-rss-admin.js

Kod: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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();
sorgunun tümü

Kod:Tümünü seç

bu kodda sorun var. eklenen tün rss ler sanki kontrol edilmiyor. yani her tıklamada/sorgulamada/tetiklemede kayıtlı rss leri ilk sıradan başlıyor bu durumda sürekli güncellenen rss den öteye gidemiyor. her tıklanmada en son rss den sonrakini sorgulaması gerekiyor. ilgilenir misin
/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/genel-rss-haber-scraper.php
/var/www/html/wp/wp-content/plugins/genel-rss-haber-scraper/js/genel-rss-admin.js
genel-rss-haber-scraper.php içeriği
<?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() {
        // Ayarları kaydederken sanitize callback ekliyoruz.
        register_setting( 'genel_rss_haber_scraper_options', $this->option_name, array( $this, 'sanitize_options' ) );
    }

    /**
     * Ayarları sanitize eder.
     *
     * @param array $options Gönderilen ayarlar dizisi.
     * @return array Temizlenmiş ayarlar dizisi.
     */
    public function sanitize_options( $options ) {
        if ( is_array( $options ) ) {
            foreach ( $options as $key => $source ) {
                // Eğer aktif seçeneği gönderilmemişse 0 yapıyoruz.
                $options[$key]['active'] = isset( $source['active'] ) ? 1 : 0;
                // Link seçeneği için de aynı işlemi yapıyoruz.
                $options[$key]['add_link'] = isset( $source['add_link'] ) ? 1 : 0;
                
                // Diğer alanları da uygun şekilde sanitize ediyoruz.
                $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() {
        // Kayıtlı RSS kaynaklarını alıyoruz
        $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'] : '';
                                // Varsayılan olarak aktif; veritabanında 0 kaydedildiyse işaretlenmeyecek.
                                $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ı parça parça (batch) kontrol ederek yapılır.</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');
                $('#fetch-rss-news').on('click', function() {
                    log.html('<p>Haber çekme işlemi başlatıldı...</p>');
                    processBatch(0);
                });
                
                function processBatch(offset) {
                    $.ajax({
                        url: ajaxurl,
                        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>');
                                // Eğer bu döngüde yeni haber eklendiyse offset’i döngüye devam etmek için kullanıyoruz.
                                if ( response.data.new_posts > 0 ) {
                                    processBatch( response.data.next_offset );
                                } else {
                                    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);

        $offset = isset( $_POST['offset'] ) ? intval( $_POST['offset'] ) : 0;
        $batch_size = 2;
        $result = $this->fetch_news_batch( $offset, $batch_size );
        
        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']
            ) );
        } else {
            wp_send_json_success( array( 
                'message'     => 'İşlenen ' . $result['processed'] . ' kaynaktan yeni haber bulunamadı.',
                'new_posts'   => 0,
                'next_offset' => $result['next_offset']
            ) );
        }
    }

    // AJAX: Bağlantı kontrolü için RSS adresi ve etiket bilgisini kontrol eder
    public function handle_connection_check() {
        $rss_url = isset( $_POST['rss_url'] ) ? esc_url_raw( $_POST['rss_url'] ) : '';
        $tag     = isset( $_POST['tag'] ) ? sanitize_text_field( $_POST['tag'] ) : '';

        if ( empty( $rss_url ) || empty( $tag ) ) {
            wp_send_json_error( array( 'message' => 'RSS URL ve Etiket bilgisi gerekli.' ) );
        }

        $rss_feed = @simplexml_load_file( $rss_url );
        if ( ! $rss_feed ) {
            wp_send_json_error( array( 'message' => 'RSS beslemesi yüklenemedi.' ) );
        }

        if ( $tag === 'item' && isset( $rss_feed->channel->item ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <item> bulundu.' ) );
        } elseif ( $tag === 'entry' && isset( $rss_feed->entry ) ) {
            wp_send_json_success( array( 'message' => 'Bağlantı başarılı: <entry> bulundu.' ) );
        } else {
            wp_send_json_error( array( 'message' => 'Belirtilen etiket bulunamadı.' ) );
        }
    }

    /**
     * Belirtilen offset ve batch size'a göre RSS kaynaklarını kontrol eder.
     * Döngü sonunda, tüm kaynaklar işlendiğinde offset 0 olarak ayarlanır (yani döngü yeniden başlar).
     *
     * @param int $offset İşleme başlanacak kaynak indeksi.
     * @param int $batch_size Bir istekte işlenecek kaynak sayısı.
     * @return array İşlenen kaynak sayısı, eklenen yeni haber sayısı ve sonraki offset.
     */
    private function fetch_news_batch( $offset, $batch_size ) {
        $sources = get_option( $this->option_name, array() );
        $total = count( $sources );
        if ( $total === 0 ) {
            return array( 'processed' => 0, 'new_posts' => 0, 'next_offset' => null );
        }
        $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++;
        }
        // Eğer döngü sona erdiyse (tüm kaynaklar işlendi) offset’i 0 yapıyoruz.
        $next_offset = ($offset + $batch_size) >= $total ? 0 : ($offset + $batch_size);
        
        return array(
            'processed'   => $processed,
            'new_posts'   => $new_posts,
            'next_offset' => $next_offset
        );
    }

    /**
     * Verilen bir RSS kaynağından (tek kaynak) haber çekmeye çalışır.
     *
     * @param array $source Kaynak bilgileri.
     * @return int Eklenen yeni haber sayısı.
     */
    private function process_source( $source ) {
        // Eğer kaynak devre dışıysa işleme almayız.
        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ç, ilk kelimeyi atlayarak
     * büyük harfli (ilk harfi büyük) 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();