diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 88d8fd7..38cc3d1 100755 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -121,6 +121,7 @@ prautoblogger/ │ │ ├── class-dashboard-widget.php # WP Dashboard widget showing generation status │ │ ├── class-post-metabox.php # Metabox on posts showing generation metadata │ │ ├── class-metrics-page.php # Admin page for cost dashboard and content scores +│ │ ├── class-ideas-browser.php # Browse all analysis results (article ideas) │ │ ├── class-review-queue.php # Approve/edit/reject queue for generated drafts │ │ └── class-log-viewer.php # Activity log viewer with level filtering │ │ diff --git a/CHANGELOG.md b/CHANGELOG.md index 27332f0..cd44cd5 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to PRAutoBlogger will be documented in this file. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project uses [Semantic Versioning](https://semver.org/). +## [0.5.1] — 2026-04-20 + +### Added +- **Ideas browser admin page.** New "Ideas" submenu under PRAutoBlogger showing + all article ideas collected by the content analyzer. Displays suggested title, + topic, type (question/complaint/comparison/news/guide), relevance score bar, + frequency, key points, and target keywords. Filterable by type with count + badges. Paginated at 30 per page, newest first. + ## [0.5.0] — 2026-04-20 ### Added diff --git a/includes/admin/class-admin-page.php b/includes/admin/class-admin-page.php index 728f478..f6f319e 100755 --- a/includes/admin/class-admin-page.php +++ b/includes/admin/class-admin-page.php @@ -58,6 +58,7 @@ class PRAutoBlogger_Admin_Page { 'toplevel_page_' . self::PAGE_SLUG, 'prautoblogger_page_prautoblogger-metrics', 'prautoblogger_page_prautoblogger-review-queue', + 'prautoblogger_page_prautoblogger-ideas', 'prautoblogger_page_prautoblogger-logs', ]; if ( ! in_array( $hook_suffix, $pages, true ) ) { diff --git a/includes/admin/class-ideas-browser.php b/includes/admin/class-ideas-browser.php new file mode 100644 index 0000000..e80e87e --- /dev/null +++ b/includes/admin/class-ideas-browser.php @@ -0,0 +1,135 @@ +query_ideas( $paged, $type_filter, $source_filter ); + $rows = $result['rows']; + $total = $result['total']; + $total_pages = (int) ceil( $total / self::PER_PAGE ); + $type_counts = $this->get_type_counts(); + + include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/ideas-browser.php'; + } + + /** + * Query analysis results with optional filtering and pagination. + * + * Side effects: database SELECT. + * + * @param int $paged Page number (1-based). + * @param string $type Filter by analysis_type (empty = all). + * @param string $source Filter: 'llm_research' or 'reddit' based on source_ids content. + * @return array{rows: array[], total: int} + */ + private function query_ideas( int $paged, string $type, string $source ): array { + global $wpdb; + $table = $wpdb->prefix . 'prautoblogger_analysis_results'; + $where = []; + $params = []; + + if ( '' !== $type ) { + $where[] = 'analysis_type = %s'; + $params[] = $type; + } + + $where_sql = empty( $where ) ? '' : 'WHERE ' . implode( ' AND ', $where ); + $offset = ( $paged - 1 ) * self::PER_PAGE; + + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + $total = (int) $wpdb->get_var( + empty( $params ) + ? "SELECT COUNT(*) FROM {$table} {$where_sql}" + : $wpdb->prepare( "SELECT COUNT(*) FROM {$table} {$where_sql}", ...$params ) + ); + + $order_sql = 'ORDER BY analyzed_at DESC, relevance_score DESC'; + $limit_sql = sprintf( 'LIMIT %d OFFSET %d', self::PER_PAGE, $offset ); + $full_sql = "SELECT * FROM {$table} {$where_sql} {$order_sql} {$limit_sql}"; + + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + $rows = empty( $params ) + ? $wpdb->get_results( $full_sql, ARRAY_A ) + : $wpdb->get_results( $wpdb->prepare( $full_sql, ...$params ), ARRAY_A ); + + return [ + 'rows' => $rows ?: [], + 'total' => $total, + ]; + } + + /** + * Get counts per analysis_type for the filter badges. + * + * Side effects: database SELECT. + * + * @return array Map of analysis_type => count. + */ + private function get_type_counts(): array { + global $wpdb; + $table = $wpdb->prefix . 'prautoblogger_analysis_results'; + + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery + $rows = $wpdb->get_results( + "SELECT analysis_type, COUNT(*) AS cnt FROM {$table} GROUP BY analysis_type ORDER BY cnt DESC", + ARRAY_A + ); + + $counts = []; + foreach ( $rows ?: [] as $row ) { + $counts[ $row['analysis_type'] ] = (int) $row['cnt']; + } + return $counts; + } +} diff --git a/includes/class-prautoblogger.php b/includes/class-prautoblogger.php index f9b884c..cb641df 100644 --- a/includes/class-prautoblogger.php +++ b/includes/class-prautoblogger.php @@ -73,6 +73,7 @@ class PRAutoBlogger { $review_queue = new PRAutoBlogger_Review_Queue(); add_action( 'admin_menu', [ $review_queue, 'on_register_menu' ] ); + add_action( 'admin_menu', [ new PRAutoBlogger_Ideas_Browser(), 'on_register_menu' ] ); add_action( 'admin_menu', [ new PRAutoBlogger_Log_Viewer(), 'on_register_menu' ] ); ( new PRAutoBlogger_Post_List_Columns() )->register(); diff --git a/prautoblogger.php b/prautoblogger.php index a1795fc..5c01fc7 100644 --- a/prautoblogger.php +++ b/prautoblogger.php @@ -8,7 +8,7 @@ declare(strict_types=1); * Plugin Name: PRAutoBlogger * Plugin URI: https://peptiderepo.com/prautoblogger * Description: Monitors social media for trending topics, generates SEO-friendly blog posts using AI, and publishes them on a daily schedule with full cost tracking and self-improvement metrics. - * Version: 0.5.0 + * Version: 0.5.1 * Requires at least: 6.0 * Requires PHP: 7.4 * Author: PeptideRepo @@ -35,7 +35,7 @@ if ( ! defined( 'ABSPATH' ) ) { | and limits without magic strings. */ -define( 'PRAUTOBLOGGER_VERSION', '0.5.0' ); +define( 'PRAUTOBLOGGER_VERSION', '0.5.1' ); define( 'PRAUTOBLOGGER_DB_VERSION', '1.1.0' ); define( 'PRAUTOBLOGGER_PLUGIN_FILE', __FILE__ ); define( 'PRAUTOBLOGGER_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); diff --git a/templates/admin/ideas-browser.php b/templates/admin/ideas-browser.php new file mode 100644 index 0000000..498185d --- /dev/null +++ b/templates/admin/ideas-browser.php @@ -0,0 +1,153 @@ + count for filter badges. + * $paged (int) — current page number. + * + * @see admin/class-ideas-browser.php — Renders this template. + */ + +if ( ! defined( 'ABSPATH' ) ) { + exit; +} + +$base_url = admin_url( 'admin.php?page=prautoblogger-ideas' ); +?> +
+

+

+ +

+ + +
+ + + + $count ) : ?> + + + + +
+ + + +
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ + +
+ +
+ +
+ + + + + = 70 ? '#00a32a' : ( $score_pct >= 40 ? '#dba617' : '#d63638' ); + ?> +
+
+
+
+ % +
+
+ +
    + +
  • + + 4 ) : ?> +
  • + more
  • + +
+ + +
+ + + + + +
+ +
+ +
+ + 1 ) : ?> +
+ add_query_arg( 'paged', '%#%' ), + 'format' => '', + 'current' => $paged, + 'total' => $total_pages, + 'prev_text' => '«', + 'next_text' => '»', + ] ) ); + ?> +
+ + +