plugin_name = $plugin_name; $this->version = $version; } /** * Enqueue admin CSS. */ public function enqueue_styles( $hook ) { if ( strpos( $hook, 'peptide-news' ) === false ) { return; } wp_enqueue_style( $this->plugin_name . '-admin', PEPTIDE_NEWS_PLUGIN_URL . 'admin/css/admin-style.css', array(), $this->version, 'all' ); } /** * Enqueue admin JS. */ public function enqueue_scripts( $hook ) { if ( strpos( $hook, 'peptide-news' ) === false ) { return; } // Chart.js for analytics dashboard. wp_enqueue_script( 'chartjs', 'https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js', array(), '4.4.0', true ); wp_enqueue_script( $this->plugin_name . '-admin', PEPTIDE_NEWS_PLUGIN_URL . 'admin/js/admin-script.js', array( 'jquery', 'chartjs' ), $this->version, true ); wp_localize_script( $this->plugin_name . '-admin', 'peptideNewsAdmin', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'rest_url' => rest_url( 'peptide-news/v1/' ), 'nonce' => wp_create_nonce( 'wp_rest' ), ) ); } /** * Add admin menu pages. */ public function add_admin_menu() { // Main menu — Analytics Dashboard. add_menu_page( __( 'Peptide News', 'peptide-news' ), __( 'Peptide News', 'peptide-news' ), 'manage_options', 'peptide-news-dashboard', array( $this, 'render_dashboard_page' ), 'dashicons-rss', 30 ); // Sub-menu — Settings. add_submenu_page( 'peptide-news-dashboard', __( 'Settings', 'peptide-news' ), __( 'Settings', 'peptide-news' ), 'manage_options', 'peptide-news-settings', array( $this, 'render_settings_page' ) ); // Sub-menu — Articles. add_submenu_page( 'peptide-news-dashboard', __( 'Articles', 'peptide-news' ), __( 'Articles', 'peptide-news' ), 'manage_options', 'peptide-news-articles', array( $this, 'render_articles_page' ) ); } /** * Register all settings. */ public function register_settings() { // --- General section --- add_settings_section( 'peptide_news_general', __( 'General Settings', 'peptide-news' ), function () { echo '
' . esc_html__( 'Configure how and when peptide news articles are fetched.', 'peptide-news' ) . '
'; }, 'peptide-news-settings' ); $this->add_setting( 'fetch_interval', __( 'Fetch Interval', 'peptide-news' ), 'render_fetch_interval_field', 'peptide_news_general' ); $this->add_setting( 'articles_count', __( 'Articles to Display', 'peptide-news' ), 'render_articles_count_field', 'peptide_news_general' ); $this->add_setting( 'search_keywords', __( 'Search Keywords', 'peptide-news' ), 'render_search_keywords_field', 'peptide_news_general' ); // --- RSS section --- add_settings_section( 'peptide_news_rss', __( 'RSS Feed Sources', 'peptide-news' ), function () { echo '' . esc_html__( 'Add RSS feed URLs, one per line.', 'peptide-news' ) . '
'; }, 'peptide-news-settings' ); $this->add_setting( 'rss_enabled', __( 'Enable RSS Feeds', 'peptide-news' ), 'render_rss_enabled_field', 'peptide_news_rss' ); $this->add_setting( 'rss_feeds', __( 'RSS Feed URLs', 'peptide-news' ), 'render_rss_feeds_field', 'peptide_news_rss' ); // --- NewsAPI section --- add_settings_section( 'peptide_news_newsapi', __( 'NewsAPI.org', 'peptide-news' ), function () { echo '' . esc_html__( 'Optional. Get a free API key at newsapi.org.', 'peptide-news' ) . '
'; }, 'peptide-news-settings' ); $this->add_setting( 'newsapi_enabled', __( 'Enable NewsAPI', 'peptide-news' ), 'render_newsapi_enabled_field', 'peptide_news_newsapi' ); $this->add_setting( 'newsapi_key', __( 'API Key', 'peptide-news' ), 'render_newsapi_key_field', 'peptide_news_newsapi' ); // --- Analytics section --- add_settings_section( 'peptide_news_analytics_section', __( 'Analytics', 'peptide-news' ), function () { echo '' . esc_html__( 'Configure click tracking and data retention.', 'peptide-news' ) . '
'; }, 'peptide-news-settings' ); $this->add_setting( 'article_retention', __( 'Article Retention (days)', 'peptide-news' ), 'render_article_retention_field', 'peptide_news_analytics_section' ); $this->add_setting( 'analytics_retention', __( 'Analytics Data Retention (days)', 'peptide-news' ), 'render_retention_field', 'peptide_news_analytics_section' ); $this->add_setting( 'anonymize_ip', __( 'Anonymize IPs', 'peptide-news' ), 'render_anonymize_ip_field', 'peptide_news_analytics_section' ); } /** * Helper: register a single setting with a field callback. */ private function add_setting( $key, $label, $callback, $section ) { $option_name = "peptide_news_{$key}"; register_setting( 'peptide_news_settings_group', $option_name ); add_settings_field( $option_name, $label, array( $this, $callback ), 'peptide-news-settings', $section ); } // --- Field renderers --- public function render_fetch_interval_field() { $value = get_option( 'peptide_news_fetch_interval', 'twicedaily' ); $options = array( 'every_fifteen_minutes' => __( 'Every 15 minutes', 'peptide-news' ), 'every_thirty_minutes' => __( 'Every 30 minutes', 'peptide-news' ), 'hourly' => __( 'Hourly', 'peptide-news' ), 'every_four_hours' => __( 'Every 4 hours', 'peptide-news' ), 'every_six_hours' => __( 'Every 6 hours', 'peptide-news' ), 'twicedaily' => __( 'Twice daily', 'peptide-news' ), 'daily' => __( 'Daily', 'peptide-news' ), ); echo ''; echo '' . esc_html__( 'How often to check for new articles. After changing, deactivate and reactivate the plugin.', 'peptide-news' ) . '
'; } public function render_articles_count_field() { $value = get_option( 'peptide_news_articles_count', 10 ); printf( '', absint( $value ) ); echo '' . esc_html__( 'Number of articles to display in the shortcode/widget.', 'peptide-news' ) . '
'; } public function render_search_keywords_field() { $value = get_option( 'peptide_news_search_keywords', '' ); printf( '', esc_attr( $value ) ); echo '' . esc_html__( 'Comma-separated keywords for NewsAPI searches.', 'peptide-news' ) . '
'; } public function render_rss_enabled_field() { $value = get_option( 'peptide_news_rss_enabled', 1 ); printf( '', checked( $value, 1, false ), esc_html__( 'Fetch articles from RSS feeds', 'peptide-news' ) ); } public function render_rss_feeds_field() { $value = get_option( 'peptide_news_rss_feeds', '' ); printf( '', esc_textarea( $value ) ); } public function render_newsapi_enabled_field() { $value = get_option( 'peptide_news_newsapi_enabled', 0 ); printf( '', checked( $value, 1, false ), esc_html__( 'Fetch articles from NewsAPI.org', 'peptide-news' ) ); } public function render_newsapi_key_field() { $value = get_option( 'peptide_news_newsapi_key', '' ); printf( '', esc_attr( $value ) ); } public function render_article_retention_field() { $value = get_option( 'peptide_news_article_retention', 90 ); printf( '', absint( $value ) ); echo '' . esc_html__( 'How long to keep fetched articles before deactivating them.', 'peptide-news' ) . '
'; } public function render_retention_field() { $value = get_option( 'peptide_news_analytics_retention', 365 ); printf( '', absint( $value ) ); echo '' . esc_html__( 'How long to keep click analytics data.', 'peptide-news' ) . '
'; } public function render_anonymize_ip_field() { $value = get_option( 'peptide_news_anonymize_ip', 1 ); printf( '', checked( $value, 1, false ), esc_html__( 'Anonymize IP addresses for GDPR compliance', 'peptide-news' ) ); } // --- Page renderers --- public function render_settings_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } // Handle manual fetch trigger. if ( isset( $_POST['peptide_news_fetch_now'] ) && check_admin_referer( 'peptide_news_fetch_now_action' ) ) { $fetcher = new Peptide_News_Fetcher(); $fetcher->fetch_all_sources(); echo '' . esc_html__( 'Fetch completed!', 'peptide-news' ) . '
%s: %s | %s: %d | %s: %d
', esc_html__( 'Last fetch', 'peptide-news' ), esc_html( $last_fetch['time'] ), esc_html__( 'Found', 'peptide-news' ), $last_fetch['found'], esc_html__( 'New stored', 'peptide-news' ), $last_fetch['new_stored'] ); } // Settings form. echo ''; // Shortcode usage info. echo '' . esc_html__( 'Shortcode:', 'peptide-news' ) . ' [peptide_news] ' .
esc_html__( 'or', 'peptide-news' ) . ' [peptide_news count="5"]
' . esc_html__( 'Widget:', 'peptide-news' ) . ' ' . esc_html__( 'Add "Peptide News" from Appearance > Widgets.', 'peptide-news' ) . '
'; echo '