Initial commit: PRAutoBlogger v0.1.0 with frontend posts widget
This commit is contained in:
@@ -4,12 +4,12 @@ declare(strict_types=1);
|
||||
/**
|
||||
* Displays admin notices for onboarding, errors, and budget warnings.
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() on `admin_notices`.
|
||||
* Dependencies: Autoblogger_Cost_Tracker (for budget warnings).
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() on `admin_notices`.
|
||||
* Dependencies: PRAutoBlogger_Cost_Tracker (for budget warnings).
|
||||
*
|
||||
* @see class-autoblogger.php — Registers the hook.
|
||||
* @see class-prautoblogger.php — Registers the hook.
|
||||
*/
|
||||
class Autoblogger_Admin_Notices {
|
||||
class PRAutoBlogger_Admin_Notices {
|
||||
|
||||
/**
|
||||
* Display relevant admin notices.
|
||||
@@ -32,16 +32,16 @@ class Autoblogger_Admin_Notices {
|
||||
* @return void
|
||||
*/
|
||||
private function check_api_key_notice(): void {
|
||||
$api_key = get_option( 'autoblogger_openrouter_api_key', '' );
|
||||
$api_key = get_option( 'prautoblogger_openrouter_api_key', '' );
|
||||
if ( '' !== $api_key ) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf(
|
||||
'<div class="notice notice-warning is-dismissible"><p>%s <a href="%s">%s</a></p></div>',
|
||||
esc_html__( 'AutoBlogger: OpenRouter API key is not configured. Content generation is disabled.', 'autoblogger' ),
|
||||
esc_url( admin_url( 'admin.php?page=autoblogger-settings' ) ),
|
||||
esc_html__( 'Configure now', 'autoblogger' )
|
||||
esc_html__( 'PRAutoBlogger: OpenRouter API key is not configured. Content generation is disabled.', 'prautoblogger' ),
|
||||
esc_url( admin_url( 'admin.php?page=prautoblogger-settings' ) ),
|
||||
esc_html__( 'Configure now', 'prautoblogger' )
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,20 +51,20 @@ class Autoblogger_Admin_Notices {
|
||||
* @return void
|
||||
*/
|
||||
private function check_budget_notice(): void {
|
||||
$cost_tracker = new Autoblogger_Cost_Tracker();
|
||||
$cost_tracker = new PRAutoBlogger_Cost_Tracker();
|
||||
$utilization = $cost_tracker->get_budget_utilization();
|
||||
|
||||
if ( $utilization >= 100.0 ) {
|
||||
printf(
|
||||
'<div class="notice notice-error"><p>%s</p></div>',
|
||||
esc_html__( 'AutoBlogger: Monthly API budget EXCEEDED. Content generation is paused until next month or budget increase.', 'autoblogger' )
|
||||
esc_html__( 'PRAutoBlogger: Monthly API budget EXCEEDED. Content generation is paused until next month or budget increase.', 'prautoblogger' )
|
||||
);
|
||||
} elseif ( $utilization >= 80.0 ) {
|
||||
printf(
|
||||
'<div class="notice notice-warning"><p>%s</p></div>',
|
||||
esc_html( sprintf(
|
||||
/* translators: %s: budget utilization percentage */
|
||||
__( 'AutoBlogger: Monthly API budget is at %.0f%%. Consider increasing the budget or reducing daily article count.', 'autoblogger' ),
|
||||
__( 'PRAutoBlogger: Monthly API budget is at %.0f%%. Consider increasing the budget or reducing daily article count.', 'prautoblogger' ),
|
||||
$utilization
|
||||
) )
|
||||
);
|
||||
@@ -77,20 +77,20 @@ class Autoblogger_Admin_Notices {
|
||||
* @return void
|
||||
*/
|
||||
private function check_subreddit_notice(): void {
|
||||
$subreddits = json_decode( get_option( 'autoblogger_target_subreddits', '[]' ), true );
|
||||
$subreddits = json_decode( get_option( 'prautoblogger_target_subreddits', '[]' ), true );
|
||||
if ( ! empty( $subreddits ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only show on our settings page.
|
||||
$screen = get_current_screen();
|
||||
if ( ! $screen || 'toplevel_page_autoblogger-settings' !== $screen->id ) {
|
||||
if ( ! $screen || 'toplevel_page_prautoblogger-settings' !== $screen->id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf(
|
||||
'<div class="notice notice-info is-dismissible"><p>%s</p></div>',
|
||||
esc_html__( 'AutoBlogger: No subreddits configured. Add target subreddits in Source Configuration to start collecting data.', 'autoblogger' )
|
||||
esc_html__( 'PRAutoBlogger: No subreddits configured. Add target subreddits in Source Configuration to start collecting data.', 'prautoblogger' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Registers and renders the main AutoBlogger settings page in wp-admin.
|
||||
* Registers and renders the main PRAutoBlogger settings page in wp-admin.
|
||||
*
|
||||
* Uses the WordPress Settings API for option registration, sanitization, and rendering.
|
||||
* Settings are defined as a declarative array — adding a new setting is one array entry.
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() registers menu and settings hooks.
|
||||
* Dependencies: Autoblogger_Encryption (for API key storage), Autoblogger_Settings_Fields.
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() registers menu and settings hooks.
|
||||
* Dependencies: PRAutoBlogger_Encryption (for API key storage), PRAutoBlogger_Settings_Fields.
|
||||
*
|
||||
* @see class-autoblogger.php — Registers hooks that call this class.
|
||||
* @see class-prautoblogger.php — Registers hooks that call this class.
|
||||
* @see class-settings-fields.php — Defines all settings fields and sections.
|
||||
* @see CONVENTIONS.md — "How To: Add a New Admin Setting".
|
||||
*/
|
||||
class Autoblogger_Admin_Page {
|
||||
class PRAutoBlogger_Admin_Page {
|
||||
|
||||
private const PAGE_SLUG = 'autoblogger-settings';
|
||||
private const OPTION_GROUP = 'autoblogger_settings_group';
|
||||
private const PAGE_SLUG = 'prautoblogger-settings';
|
||||
private const OPTION_GROUP = 'prautoblogger_settings_group';
|
||||
|
||||
/** Register the top-level AutoBlogger menu item. */
|
||||
/** Register the top-level PRAutoBlogger menu item. */
|
||||
public function on_register_menu(): void {
|
||||
add_menu_page(
|
||||
__( 'AutoBlogger', 'autoblogger' ),
|
||||
__( 'AutoBlogger', 'autoblogger' ),
|
||||
__( 'PRAutoBlogger', 'prautoblogger' ),
|
||||
__( 'PRAutoBlogger', 'prautoblogger' ),
|
||||
'manage_options',
|
||||
self::PAGE_SLUG,
|
||||
[ $this, 'render_page' ],
|
||||
@@ -34,15 +34,15 @@ class Autoblogger_Admin_Page {
|
||||
|
||||
/** Register all settings with the WordPress Settings API. */
|
||||
public function on_register_settings(): void {
|
||||
$sections = Autoblogger_Settings_Fields::get_sections();
|
||||
$fields = Autoblogger_Settings_Fields::get_fields();
|
||||
$sections = PRAutoBlogger_Settings_Fields::get_sections();
|
||||
$fields = PRAutoBlogger_Settings_Fields::get_fields();
|
||||
|
||||
foreach ( $sections as $section_id => $section ) {
|
||||
add_settings_section( $section_id, $section['title'], '__return_empty_string', self::PAGE_SLUG );
|
||||
}
|
||||
|
||||
foreach ( $fields as $field ) {
|
||||
$section = $field['section'] ?? 'autoblogger_api';
|
||||
$section = $field['section'] ?? 'prautoblogger_api';
|
||||
register_setting( self::OPTION_GROUP, $field['id'], [
|
||||
'type' => $field['wp_type'] ?? 'string',
|
||||
'sanitize_callback' => [ $this, 'sanitize_field' ],
|
||||
@@ -52,30 +52,30 @@ class Autoblogger_Admin_Page {
|
||||
}
|
||||
}
|
||||
|
||||
/** Enqueue admin CSS and JS on all AutoBlogger admin pages. */
|
||||
/** Enqueue admin CSS and JS on all PRAutoBlogger admin pages. */
|
||||
public function on_enqueue_assets( string $hook_suffix ): void {
|
||||
$pages = [
|
||||
'toplevel_page_' . self::PAGE_SLUG,
|
||||
'autoblogger_page_autoblogger-metrics',
|
||||
'autoblogger_page_autoblogger-review-queue',
|
||||
'autoblogger_page_autoblogger-logs',
|
||||
'prautoblogger_page_prautoblogger-metrics',
|
||||
'prautoblogger_page_prautoblogger-review-queue',
|
||||
'prautoblogger_page_prautoblogger-logs',
|
||||
];
|
||||
if ( ! in_array( $hook_suffix, $pages, true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_enqueue_style( 'autoblogger-admin', AUTOBLOGGER_PLUGIN_URL . 'assets/css/admin.css', [], AUTOBLOGGER_VERSION );
|
||||
wp_enqueue_script( 'autoblogger-admin', AUTOBLOGGER_PLUGIN_URL . 'assets/js/admin.js', [ 'jquery' ], AUTOBLOGGER_VERSION, true );
|
||||
wp_enqueue_style( 'prautoblogger-admin', PRAUTOBLOGGER_PLUGIN_URL . 'assets/css/admin.css', [], PRAUTOBLOGGER_VERSION );
|
||||
wp_enqueue_script( 'prautoblogger-admin', PRAUTOBLOGGER_PLUGIN_URL . 'assets/js/admin.js', [ 'jquery' ], PRAUTOBLOGGER_VERSION, true );
|
||||
|
||||
wp_localize_script( 'autoblogger-admin', 'autobloggerAdmin', [
|
||||
wp_localize_script( 'prautoblogger-admin', 'prautobloggerAdmin', [
|
||||
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
|
||||
'generateNonce' => wp_create_nonce( 'autoblogger_generate_now' ),
|
||||
'testNonce' => wp_create_nonce( 'autoblogger_test_connection' ),
|
||||
'reviewNonce' => wp_create_nonce( 'autoblogger_review_queue' ),
|
||||
'generatingText' => __( 'Generating...', 'autoblogger' ),
|
||||
'generateText' => __( 'Generate Now', 'autoblogger' ),
|
||||
'testingText' => __( 'Testing...', 'autoblogger' ),
|
||||
'testText' => __( 'Test Connections', 'autoblogger' ),
|
||||
'generateNonce' => wp_create_nonce( 'prautoblogger_generate_now' ),
|
||||
'testNonce' => wp_create_nonce( 'prautoblogger_test_connection' ),
|
||||
'reviewNonce' => wp_create_nonce( 'prautoblogger_review_queue' ),
|
||||
'generatingText' => __( 'Generating...', 'prautoblogger' ),
|
||||
'generateText' => __( 'Generate Now', 'prautoblogger' ),
|
||||
'testingText' => __( 'Testing...', 'prautoblogger' ),
|
||||
'testText' => __( 'Test Connections', 'prautoblogger' ),
|
||||
] );
|
||||
}
|
||||
|
||||
@@ -84,9 +84,9 @@ class Autoblogger_Admin_Page {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
$sections = Autoblogger_Settings_Fields::get_sections();
|
||||
$fields = Autoblogger_Settings_Fields::get_fields();
|
||||
include AUTOBLOGGER_PLUGIN_DIR . 'templates/admin/settings-page.php';
|
||||
$sections = PRAutoBlogger_Settings_Fields::get_sections();
|
||||
$fields = PRAutoBlogger_Settings_Fields::get_fields();
|
||||
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/settings-page.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +102,7 @@ class Autoblogger_Admin_Page {
|
||||
$value = get_option( $args['id'], $default );
|
||||
|
||||
if ( 'password' === $type && '' !== $value ) {
|
||||
$decrypted = Autoblogger_Encryption::decrypt( $value );
|
||||
$decrypted = PRAutoBlogger_Encryption::decrypt( $value );
|
||||
$value = '' !== $decrypted ? '••••••••' : '';
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ class Autoblogger_Admin_Page {
|
||||
|
||||
case 'password':
|
||||
printf( '<input type="password" id="%s" name="%s" value="" class="ab-input" placeholder="%s" autocomplete="off" />',
|
||||
$id, $id, '' !== $value ? esc_attr__( 'Saved (enter new value to change)', 'autoblogger' ) : '' );
|
||||
$id, $id, '' !== $value ? esc_attr__( 'Saved (enter new value to change)', 'prautoblogger' ) : '' );
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
@@ -152,11 +152,11 @@ class Autoblogger_Admin_Page {
|
||||
break;
|
||||
|
||||
case 'author_select':
|
||||
wp_dropdown_users( [ 'name' => $id, 'id' => $id, 'selected' => absint( $value ), 'show_option_none' => __( '— Auto (first admin) —', 'autoblogger' ), 'option_none_value' => '0', 'class' => 'ab-select' ] );
|
||||
wp_dropdown_users( [ 'name' => $id, 'id' => $id, 'selected' => absint( $value ), 'show_option_none' => __( '— Auto (first admin) —', 'prautoblogger' ), 'option_none_value' => '0', 'class' => 'ab-select' ] );
|
||||
break;
|
||||
|
||||
case 'category_select':
|
||||
wp_dropdown_categories( [ 'name' => $id, 'id' => $id, 'selected' => absint( $value ), 'show_option_none' => __( '— Auto-assign by type —', 'autoblogger' ), 'option_none_value' => '0', 'class' => 'ab-select', 'hide_empty' => false ] );
|
||||
wp_dropdown_categories( [ 'name' => $id, 'id' => $id, 'selected' => absint( $value ), 'show_option_none' => __( '— Auto-assign by type —', 'prautoblogger' ), 'option_none_value' => '0', 'class' => 'ab-select', 'hide_empty' => false ] );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -181,13 +181,13 @@ class Autoblogger_Admin_Page {
|
||||
$option_name = substr( $filter, strlen( 'sanitize_option_' ) );
|
||||
}
|
||||
|
||||
$encrypted = [ 'autoblogger_openrouter_api_key', 'autoblogger_reddit_client_secret', 'autoblogger_ga4_credentials_json' ];
|
||||
$encrypted = [ 'prautoblogger_openrouter_api_key', 'prautoblogger_reddit_client_secret', 'prautoblogger_ga4_credentials_json' ];
|
||||
if ( in_array( $option_name, $encrypted, true ) ) {
|
||||
if ( '' === $value ) { return get_option( $option_name, '' ); }
|
||||
return Autoblogger_Encryption::encrypt( sanitize_text_field( $value ) );
|
||||
return PRAutoBlogger_Encryption::encrypt( sanitize_text_field( $value ) );
|
||||
}
|
||||
|
||||
$json_fields = [ 'autoblogger_target_subreddits', 'autoblogger_topic_exclusions', 'autoblogger_enabled_sources' ];
|
||||
$json_fields = [ 'prautoblogger_target_subreddits', 'prautoblogger_topic_exclusions', 'prautoblogger_enabled_sources' ];
|
||||
if ( in_array( $option_name, $json_fields, true ) ) {
|
||||
if ( is_array( $value ) ) { return wp_json_encode( array_values( array_map( 'sanitize_text_field', $value ) ) ); }
|
||||
if ( is_string( $value ) && '[' !== substr( trim( $value ), 0, 1 ) ) {
|
||||
@@ -197,7 +197,7 @@ class Autoblogger_Admin_Page {
|
||||
return sanitize_text_field( $value );
|
||||
}
|
||||
|
||||
$numeric = [ 'autoblogger_daily_article_target', 'autoblogger_monthly_budget_usd', 'autoblogger_min_word_count', 'autoblogger_max_word_count', 'autoblogger_default_author', 'autoblogger_default_category' ];
|
||||
$numeric = [ 'prautoblogger_daily_article_target', 'prautoblogger_monthly_budget_usd', 'prautoblogger_min_word_count', 'prautoblogger_max_word_count', 'prautoblogger_default_author', 'prautoblogger_default_category' ];
|
||||
if ( in_array( $option_name, $numeric, true ) ) {
|
||||
return is_numeric( $value ) ? $value : 0;
|
||||
}
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* WordPress Dashboard widget showing AutoBlogger generation status at a glance.
|
||||
* WordPress Dashboard widget showing PRAutoBlogger generation status at a glance.
|
||||
*
|
||||
* Displays: last generation time, articles generated today, monthly cost,
|
||||
* and budget utilization.
|
||||
*
|
||||
* Triggered by: Could be registered via wp_dashboard_setup hook.
|
||||
* Dependencies: Autoblogger_Cost_Tracker.
|
||||
* Dependencies: PRAutoBlogger_Cost_Tracker.
|
||||
*
|
||||
* @see class-autoblogger.php — Can register this on wp_dashboard_setup.
|
||||
* @see class-prautoblogger.php — Can register this on wp_dashboard_setup.
|
||||
*/
|
||||
class Autoblogger_Dashboard_Widget {
|
||||
class PRAutoBlogger_Dashboard_Widget {
|
||||
|
||||
/**
|
||||
* Register the dashboard widget.
|
||||
@@ -25,8 +25,8 @@ class Autoblogger_Dashboard_Widget {
|
||||
}
|
||||
|
||||
wp_add_dashboard_widget(
|
||||
'autoblogger_status',
|
||||
__( 'AutoBlogger Status', 'autoblogger' ),
|
||||
'prautoblogger_status',
|
||||
__( 'PRAutoBlogger Status', 'prautoblogger' ),
|
||||
[ $this, 'render_widget' ]
|
||||
);
|
||||
}
|
||||
@@ -37,15 +37,15 @@ class Autoblogger_Dashboard_Widget {
|
||||
* @return void
|
||||
*/
|
||||
public function render_widget(): void {
|
||||
$cost_tracker = new Autoblogger_Cost_Tracker();
|
||||
$cost_tracker = new PRAutoBlogger_Cost_Tracker();
|
||||
$monthly_spend = $cost_tracker->get_monthly_spend();
|
||||
$budget = (float) get_option( 'autoblogger_monthly_budget_usd', 50.00 );
|
||||
$budget = (float) get_option( 'prautoblogger_monthly_budget_usd', 50.00 );
|
||||
$utilization = $cost_tracker->get_budget_utilization();
|
||||
|
||||
$next_run = wp_next_scheduled( 'autoblogger_daily_generation' );
|
||||
$next_run = wp_next_scheduled( 'prautoblogger_daily_generation' );
|
||||
|
||||
printf( '<p><strong>%s</strong> $%.2f / $%.2f (%.0f%%)</p>',
|
||||
esc_html__( 'Monthly Spend:', 'autoblogger' ),
|
||||
esc_html__( 'Monthly Spend:', 'prautoblogger' ),
|
||||
$monthly_spend,
|
||||
$budget,
|
||||
$utilization
|
||||
@@ -53,15 +53,15 @@ class Autoblogger_Dashboard_Widget {
|
||||
|
||||
if ( false !== $next_run ) {
|
||||
printf( '<p><strong>%s</strong> %s</p>',
|
||||
esc_html__( 'Next Generation:', 'autoblogger' ),
|
||||
esc_html__( 'Next Generation:', 'prautoblogger' ),
|
||||
esc_html( wp_date( 'M j, Y g:i A', $next_run ) )
|
||||
);
|
||||
}
|
||||
|
||||
printf(
|
||||
'<p><a href="%s" class="button button-secondary">%s</a></p>',
|
||||
esc_url( admin_url( 'admin.php?page=autoblogger-metrics' ) ),
|
||||
esc_html__( 'View Full Metrics', 'autoblogger' )
|
||||
esc_url( admin_url( 'admin.php?page=prautoblogger-metrics' ) ),
|
||||
esc_html__( 'View Full Metrics', 'prautoblogger' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,29 +6,29 @@ declare(strict_types=1);
|
||||
*
|
||||
* Provides level filtering (error/warning/info/debug), text search,
|
||||
* pagination, and a one-click "Clear Old Logs" action. Reads from the
|
||||
* ab_event_log table via Autoblogger_Logger::query().
|
||||
* prab_event_log table via PRAutoBlogger_Logger::query().
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() on `admin_menu`.
|
||||
* Dependencies: Autoblogger_Logger.
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() on `admin_menu`.
|
||||
* Dependencies: PRAutoBlogger_Logger.
|
||||
*
|
||||
* @see core/class-logger.php — Writes log entries and provides query().
|
||||
* @see templates/admin/log-viewer.php — Renders the HTML.
|
||||
* @see class-autoblogger.php — Registers the AJAX clear action.
|
||||
* @see class-prautoblogger.php — Registers the AJAX clear action.
|
||||
*/
|
||||
class Autoblogger_Log_Viewer {
|
||||
class PRAutoBlogger_Log_Viewer {
|
||||
|
||||
/**
|
||||
* Register the log viewer submenu page under AutoBlogger.
|
||||
* Register the log viewer submenu page under PRAutoBlogger.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function on_register_menu(): void {
|
||||
add_submenu_page(
|
||||
'autoblogger-settings',
|
||||
__( 'Activity Log', 'autoblogger' ),
|
||||
__( 'Activity Log', 'autoblogger' ),
|
||||
'prautoblogger-settings',
|
||||
__( 'Activity Log', 'prautoblogger' ),
|
||||
__( 'Activity Log', 'prautoblogger' ),
|
||||
'manage_options',
|
||||
'autoblogger-logs',
|
||||
'prautoblogger-logs',
|
||||
[ $this, 'render_page' ]
|
||||
);
|
||||
}
|
||||
@@ -47,36 +47,36 @@ class Autoblogger_Log_Viewer {
|
||||
$search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
|
||||
$paged = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
|
||||
|
||||
$result = Autoblogger_Logger::query( $level, $search, $paged, 50 );
|
||||
$result = PRAutoBlogger_Logger::query( $level, $search, $paged, 50 );
|
||||
$rows = $result['rows'];
|
||||
$total = $result['total'];
|
||||
$total_pages = (int) ceil( $total / 50 );
|
||||
|
||||
include AUTOBLOGGER_PLUGIN_DIR . 'templates/admin/log-viewer.php';
|
||||
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/log-viewer.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX handler: clear logs older than 30 days.
|
||||
*
|
||||
* Side effects: deletes rows from ab_event_log.
|
||||
* Side effects: deletes rows from prab_event_log.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function on_ajax_clear_logs(): void {
|
||||
check_ajax_referer( 'autoblogger_clear_logs', 'nonce' );
|
||||
check_ajax_referer( 'prautoblogger_clear_logs', 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'autoblogger' ) ], 403 );
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'prautoblogger' ) ], 403 );
|
||||
return;
|
||||
}
|
||||
|
||||
$days = isset( $_POST['days'] ) ? absint( $_POST['days'] ) : 30;
|
||||
$deleted = Autoblogger_Logger::prune( $days );
|
||||
$deleted = PRAutoBlogger_Logger::prune( $days );
|
||||
|
||||
wp_send_json_success( [
|
||||
'message' => sprintf(
|
||||
/* translators: %d: number of entries deleted */
|
||||
__( '%d log entries cleared.', 'autoblogger' ),
|
||||
__( '%d log entries cleared.', 'prautoblogger' ),
|
||||
$deleted
|
||||
),
|
||||
] );
|
||||
|
||||
@@ -7,26 +7,26 @@ declare(strict_types=1);
|
||||
* Shows: monthly spend, daily cost chart, spend by pipeline stage, budget
|
||||
* utilization, top/bottom performing posts, and recent generation logs.
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() on `admin_menu`.
|
||||
* Dependencies: Autoblogger_Cost_Tracker.
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() on `admin_menu`.
|
||||
* Dependencies: PRAutoBlogger_Cost_Tracker.
|
||||
*
|
||||
* @see class-autoblogger.php — Registers the hook.
|
||||
* @see class-prautoblogger.php — Registers the hook.
|
||||
* @see core/class-cost-tracker.php — Provides cost data.
|
||||
*/
|
||||
class Autoblogger_Metrics_Page {
|
||||
class PRAutoBlogger_Metrics_Page {
|
||||
|
||||
/**
|
||||
* Register the metrics submenu page under AutoBlogger.
|
||||
* Register the metrics submenu page under PRAutoBlogger.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function on_register_menu(): void {
|
||||
add_submenu_page(
|
||||
'autoblogger-settings',
|
||||
__( 'Metrics & Costs', 'autoblogger' ),
|
||||
__( 'Metrics & Costs', 'autoblogger' ),
|
||||
'prautoblogger-settings',
|
||||
__( 'Metrics & Costs', 'prautoblogger' ),
|
||||
__( 'Metrics & Costs', 'prautoblogger' ),
|
||||
'manage_options',
|
||||
'autoblogger-metrics',
|
||||
'prautoblogger-metrics',
|
||||
[ $this, 'render_page' ]
|
||||
);
|
||||
}
|
||||
@@ -41,6 +41,6 @@ class Autoblogger_Metrics_Page {
|
||||
return;
|
||||
}
|
||||
|
||||
include AUTOBLOGGER_PLUGIN_DIR . 'templates/admin/metrics-page.php';
|
||||
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/metrics-page.php';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Adds a metabox to posts showing AutoBlogger generation metadata.
|
||||
* Adds a metabox to posts showing PRAutoBlogger generation metadata.
|
||||
*
|
||||
* Only appears on posts that were generated by AutoBlogger (checked via
|
||||
* _autoblogger_generated post meta).
|
||||
* Only appears on posts that were generated by PRAutoBlogger (checked via
|
||||
* _prautoblogger_generated post meta).
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() on `add_meta_boxes`.
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() on `add_meta_boxes`.
|
||||
* Dependencies: WordPress post meta API.
|
||||
*
|
||||
* @see class-autoblogger.php — Registers the hook.
|
||||
* @see class-prautoblogger.php — Registers the hook.
|
||||
* @see core/class-publisher.php — Writes the metadata this class displays.
|
||||
*/
|
||||
class Autoblogger_Post_Metabox {
|
||||
class PRAutoBlogger_Post_Metabox {
|
||||
|
||||
/**
|
||||
* Register the metabox for the post editor.
|
||||
@@ -27,13 +27,13 @@ class Autoblogger_Post_Metabox {
|
||||
}
|
||||
|
||||
global $post;
|
||||
if ( ! $post || '1' !== get_post_meta( $post->ID, '_autoblogger_generated', true ) ) {
|
||||
if ( ! $post || '1' !== get_post_meta( $post->ID, '_prautoblogger_generated', true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_meta_box(
|
||||
'autoblogger_generation_info',
|
||||
__( 'AutoBlogger Generation Info', 'autoblogger' ),
|
||||
'prautoblogger_generation_info',
|
||||
__( 'PRAutoBlogger Generation Info', 'prautoblogger' ),
|
||||
[ $this, 'render_metabox' ],
|
||||
'post',
|
||||
'side',
|
||||
@@ -49,6 +49,6 @@ class Autoblogger_Post_Metabox {
|
||||
* @return void
|
||||
*/
|
||||
public function render_metabox( \WP_Post $post ): void {
|
||||
include AUTOBLOGGER_PLUGIN_DIR . 'templates/admin/metabox-generation-info.php';
|
||||
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/metabox-generation-info.php';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,27 +7,27 @@ declare(strict_types=1);
|
||||
* Provides approve (publish), edit (opens WP editor), and reject (trash)
|
||||
* actions on each draft. Supports bulk approve/reject via checkboxes.
|
||||
*
|
||||
* Triggered by: Autoblogger::register_admin_hooks() on `admin_menu`.
|
||||
* Triggered by: PRAutoBlogger::register_admin_hooks() on `admin_menu`.
|
||||
* Dependencies: WordPress WP_Query, post meta API.
|
||||
*
|
||||
* @see class-autoblogger.php — Registers the hook and AJAX handlers.
|
||||
* @see class-prautoblogger.php — Registers the hook and AJAX handlers.
|
||||
* @see core/class-publisher.php — Creates the drafts this page displays.
|
||||
* @see templates/admin/review-queue.php — Renders the HTML.
|
||||
*/
|
||||
class Autoblogger_Review_Queue {
|
||||
class PRAutoBlogger_Review_Queue {
|
||||
|
||||
/**
|
||||
* Register the review queue submenu page under AutoBlogger.
|
||||
* Register the review queue submenu page under PRAutoBlogger.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function on_register_menu(): void {
|
||||
$hook = add_submenu_page(
|
||||
'autoblogger-settings',
|
||||
__( 'Review Queue', 'autoblogger' ),
|
||||
__( 'Review Queue', 'autoblogger' ),
|
||||
'prautoblogger-settings',
|
||||
__( 'Review Queue', 'prautoblogger' ),
|
||||
__( 'Review Queue', 'prautoblogger' ),
|
||||
'manage_options',
|
||||
'autoblogger-review-queue',
|
||||
'prautoblogger-review-queue',
|
||||
[ $this, 'render_page' ]
|
||||
);
|
||||
|
||||
@@ -49,7 +49,7 @@ class Autoblogger_Review_Queue {
|
||||
$paged = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
|
||||
$query = $this->get_pending_posts( $paged );
|
||||
|
||||
include AUTOBLOGGER_PLUGIN_DIR . 'templates/admin/review-queue.php';
|
||||
include PRAUTOBLOGGER_PLUGIN_DIR . 'templates/admin/review-queue.php';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +67,7 @@ class Autoblogger_Review_Queue {
|
||||
'paged' => $paged,
|
||||
'meta_query' => [
|
||||
[
|
||||
'key' => '_autoblogger_generated',
|
||||
'key' => '_prautoblogger_generated',
|
||||
'value' => '1',
|
||||
],
|
||||
],
|
||||
@@ -87,19 +87,19 @@ class Autoblogger_Review_Queue {
|
||||
* @return void
|
||||
*/
|
||||
public function on_handle_bulk_actions(): void {
|
||||
if ( ! isset( $_POST['autoblogger_bulk_action'] ) ) {
|
||||
if ( ! isset( $_POST['prautoblogger_bulk_action'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
check_admin_referer( 'autoblogger_review_queue_bulk', 'autoblogger_review_nonce' );
|
||||
check_admin_referer( 'prautoblogger_review_queue_bulk', 'prautoblogger_review_nonce' );
|
||||
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = sanitize_text_field( wp_unslash( $_POST['autoblogger_bulk_action'] ) );
|
||||
$post_ids = isset( $_POST['autoblogger_post_ids'] ) && is_array( $_POST['autoblogger_post_ids'] )
|
||||
? array_map( 'absint', $_POST['autoblogger_post_ids'] )
|
||||
$action = sanitize_text_field( wp_unslash( $_POST['prautoblogger_bulk_action'] ) );
|
||||
$post_ids = isset( $_POST['prautoblogger_post_ids'] ) && is_array( $_POST['prautoblogger_post_ids'] )
|
||||
? array_map( 'absint', $_POST['prautoblogger_post_ids'] )
|
||||
: [];
|
||||
|
||||
if ( empty( $post_ids ) ) {
|
||||
@@ -115,7 +115,7 @@ class Autoblogger_Review_Queue {
|
||||
if ( 'approve' === $action ) {
|
||||
$result = wp_update_post( [ 'ID' => $post_id, 'post_status' => 'publish' ], true );
|
||||
if ( ! is_wp_error( $result ) ) {
|
||||
update_post_meta( $post_id, '_autoblogger_approved_at', gmdate( 'c' ) );
|
||||
update_post_meta( $post_id, '_prautoblogger_approved_at', gmdate( 'c' ) );
|
||||
$count++;
|
||||
}
|
||||
} elseif ( 'reject' === $action ) {
|
||||
@@ -128,9 +128,9 @@ class Autoblogger_Review_Queue {
|
||||
|
||||
$redirect = add_query_arg(
|
||||
[
|
||||
'page' => 'autoblogger-review-queue',
|
||||
'autoblogger_bulk_done' => $count,
|
||||
'autoblogger_bulk_type' => $action,
|
||||
'page' => 'prautoblogger-review-queue',
|
||||
'prautoblogger_bulk_done' => $count,
|
||||
'prautoblogger_bulk_type' => $action,
|
||||
],
|
||||
admin_url( 'admin.php' )
|
||||
);
|
||||
@@ -147,16 +147,16 @@ class Autoblogger_Review_Queue {
|
||||
* @return void
|
||||
*/
|
||||
public function on_ajax_approve_post(): void {
|
||||
check_ajax_referer( 'autoblogger_review_queue', 'nonce' );
|
||||
check_ajax_referer( 'prautoblogger_review_queue', 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'autoblogger' ) ], 403 );
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'prautoblogger' ) ], 403 );
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
|
||||
if ( $post_id <= 0 ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Invalid post ID.', 'autoblogger' ) ] );
|
||||
wp_send_json_error( [ 'message' => __( 'Invalid post ID.', 'prautoblogger' ) ] );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,8 +167,8 @@ class Autoblogger_Review_Queue {
|
||||
return;
|
||||
}
|
||||
|
||||
update_post_meta( $post_id, '_autoblogger_approved_at', gmdate( 'c' ) );
|
||||
wp_send_json_success( [ 'message' => __( 'Post published.', 'autoblogger' ), 'post_id' => $post_id ] );
|
||||
update_post_meta( $post_id, '_prautoblogger_approved_at', gmdate( 'c' ) );
|
||||
wp_send_json_success( [ 'message' => __( 'Post published.', 'prautoblogger' ), 'post_id' => $post_id ] );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,25 +179,25 @@ class Autoblogger_Review_Queue {
|
||||
* @return void
|
||||
*/
|
||||
public function on_ajax_reject_post(): void {
|
||||
check_ajax_referer( 'autoblogger_review_queue', 'nonce' );
|
||||
check_ajax_referer( 'prautoblogger_review_queue', 'nonce' );
|
||||
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'autoblogger' ) ], 403 );
|
||||
wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'prautoblogger' ) ], 403 );
|
||||
return;
|
||||
}
|
||||
|
||||
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
|
||||
if ( $post_id <= 0 ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Invalid post ID.', 'autoblogger' ) ] );
|
||||
wp_send_json_error( [ 'message' => __( 'Invalid post ID.', 'prautoblogger' ) ] );
|
||||
return;
|
||||
}
|
||||
|
||||
$result = wp_trash_post( $post_id );
|
||||
if ( false === $result || null === $result ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Failed to reject post.', 'autoblogger' ) ] );
|
||||
wp_send_json_error( [ 'message' => __( 'Failed to reject post.', 'prautoblogger' ) ] );
|
||||
return;
|
||||
}
|
||||
|
||||
wp_send_json_success( [ 'message' => __( 'Post rejected.', 'autoblogger' ), 'post_id' => $post_id ] );
|
||||
wp_send_json_success( [ 'message' => __( 'Post rejected.', 'prautoblogger' ), 'post_id' => $post_id ] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Declarative settings fields and sections for the AutoBlogger admin page.
|
||||
* Declarative settings fields and sections for the PRAutoBlogger admin page.
|
||||
*
|
||||
* Centralizes all field and section definitions in one place, making it trivial
|
||||
* to add new settings (just add one array entry). Decoupled from page rendering logic.
|
||||
*
|
||||
* Triggered by: Autoblogger_Admin_Page::on_register_settings() calls static methods here.
|
||||
* Triggered by: PRAutoBlogger_Admin_Page::on_register_settings() calls static methods here.
|
||||
* Dependencies: None — contains only data definitions and static methods.
|
||||
*
|
||||
* @see admin/class-admin-page.php — Calls get_sections() and get_fields() to register settings.
|
||||
* @see CONVENTIONS.md — "How To: Add a New Admin Setting".
|
||||
*/
|
||||
class Autoblogger_Settings_Fields {
|
||||
class PRAutoBlogger_Settings_Fields {
|
||||
|
||||
/**
|
||||
* Get all settings sections. Each section maps to a tab in the admin UI.
|
||||
@@ -22,40 +22,40 @@ class Autoblogger_Settings_Fields {
|
||||
*/
|
||||
public static function get_sections(): array {
|
||||
return [
|
||||
'autoblogger_api' => [
|
||||
'title' => __( 'API Keys', 'autoblogger' ),
|
||||
'prautoblogger_api' => [
|
||||
'title' => __( 'API Keys', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-admin-network',
|
||||
'description' => __( 'Connect your external services. Keys are encrypted at rest.', 'autoblogger' ),
|
||||
'description' => __( 'Connect your external services. Keys are encrypted at rest.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_models' => [
|
||||
'title' => __( 'AI Models', 'autoblogger' ),
|
||||
'prautoblogger_models' => [
|
||||
'title' => __( 'AI Models', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-superhero-alt',
|
||||
'description' => __( 'Choose which models power each stage of the pipeline.', 'autoblogger' ),
|
||||
'description' => __( 'Choose which models power each stage of the pipeline.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_content' => [
|
||||
'title' => __( 'Content', 'autoblogger' ),
|
||||
'prautoblogger_content' => [
|
||||
'title' => __( 'Content', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-edit-large',
|
||||
'description' => __( 'Control tone, length, pipeline mode, and topic guardrails.', 'autoblogger' ),
|
||||
'description' => __( 'Control tone, length, pipeline mode, and topic guardrails.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_sources' => [
|
||||
'title' => __( 'Sources', 'autoblogger' ),
|
||||
'prautoblogger_sources' => [
|
||||
'title' => __( 'Sources', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-rss',
|
||||
'description' => __( 'Configure where AutoBlogger finds trending topics.', 'autoblogger' ),
|
||||
'description' => __( 'Configure where PRAutoBlogger finds trending topics.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_schedule' => [
|
||||
'title' => __( 'Schedule & Budget', 'autoblogger' ),
|
||||
'prautoblogger_schedule' => [
|
||||
'title' => __( 'Schedule & Budget', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-calendar-alt',
|
||||
'description' => __( 'Set daily generation schedule, volume, and spending limits.', 'autoblogger' ),
|
||||
'description' => __( 'Set daily generation schedule, volume, and spending limits.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_publishing' => [
|
||||
'title' => __( 'Publishing', 'autoblogger' ),
|
||||
'prautoblogger_publishing' => [
|
||||
'title' => __( 'Publishing', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-megaphone',
|
||||
'description' => __( 'Control how generated content is published.', 'autoblogger' ),
|
||||
'description' => __( 'Control how generated content is published.', 'prautoblogger' ),
|
||||
],
|
||||
'autoblogger_analytics' => [
|
||||
'title' => __( 'Analytics', 'autoblogger' ),
|
||||
'prautoblogger_analytics' => [
|
||||
'title' => __( 'Analytics', 'prautoblogger' ),
|
||||
'icon' => 'dashicons-chart-area',
|
||||
'description' => __( 'Connect Google Analytics 4 for post performance scoring.', 'autoblogger' ),
|
||||
'description' => __( 'Connect Google Analytics 4 for post performance scoring.', 'prautoblogger' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
@@ -69,222 +69,222 @@ class Autoblogger_Settings_Fields {
|
||||
return [
|
||||
// ── API Keys ────────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_openrouter_api_key',
|
||||
'label' => __( 'OpenRouter API Key', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_openrouter_api_key',
|
||||
'label' => __( 'OpenRouter API Key', 'prautoblogger' ),
|
||||
'type' => 'password',
|
||||
'section' => 'autoblogger_api',
|
||||
'description' => __( 'Get your key at openrouter.ai/keys', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_api',
|
||||
'description' => __( 'Get your key at openrouter.ai/keys', 'prautoblogger' ),
|
||||
'icon' => '🔑',
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_reddit_client_id',
|
||||
'label' => __( 'Reddit Client ID', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_reddit_client_id',
|
||||
'label' => __( 'Reddit Client ID', 'prautoblogger' ),
|
||||
'type' => 'text',
|
||||
'section' => 'autoblogger_api',
|
||||
'description' => __( 'Create a script app at reddit.com/prefs/apps', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_api',
|
||||
'description' => __( 'Create a script app at reddit.com/prefs/apps', 'prautoblogger' ),
|
||||
'icon' => '🤖',
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_reddit_client_secret',
|
||||
'label' => __( 'Reddit Client Secret', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_reddit_client_secret',
|
||||
'label' => __( 'Reddit Client Secret', 'prautoblogger' ),
|
||||
'type' => 'password',
|
||||
'section' => 'autoblogger_api',
|
||||
'section' => 'prautoblogger_api',
|
||||
],
|
||||
|
||||
// ── AI Models ───────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_analysis_model',
|
||||
'label' => __( 'Analysis Model', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_analysis_model',
|
||||
'label' => __( 'Analysis Model', 'prautoblogger' ),
|
||||
'type' => 'text',
|
||||
'section' => 'autoblogger_models',
|
||||
'default' => AUTOBLOGGER_DEFAULT_ANALYSIS_MODEL,
|
||||
'description' => __( 'Used for source analysis. Pick a cheap, fast model.', 'autoblogger' ),
|
||||
'badge' => __( 'Low cost', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_models',
|
||||
'default' => PRAUTOBLOGGER_DEFAULT_ANALYSIS_MODEL,
|
||||
'description' => __( 'Used for source analysis. Pick a cheap, fast model.', 'prautoblogger' ),
|
||||
'badge' => __( 'Low cost', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_writing_model',
|
||||
'label' => __( 'Writing Model', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_writing_model',
|
||||
'label' => __( 'Writing Model', 'prautoblogger' ),
|
||||
'type' => 'text',
|
||||
'section' => 'autoblogger_models',
|
||||
'default' => AUTOBLOGGER_DEFAULT_WRITING_MODEL,
|
||||
'description' => __( 'Used for article generation. Quality matters here.', 'autoblogger' ),
|
||||
'badge' => __( 'Quality', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_models',
|
||||
'default' => PRAUTOBLOGGER_DEFAULT_WRITING_MODEL,
|
||||
'description' => __( 'Used for article generation. Quality matters here.', 'prautoblogger' ),
|
||||
'badge' => __( 'Quality', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_editor_model',
|
||||
'label' => __( 'Editor Model', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_editor_model',
|
||||
'label' => __( 'Editor Model', 'prautoblogger' ),
|
||||
'type' => 'text',
|
||||
'section' => 'autoblogger_models',
|
||||
'default' => AUTOBLOGGER_DEFAULT_EDITOR_MODEL,
|
||||
'description' => __( 'Used for the chief editor review pass.', 'autoblogger' ),
|
||||
'badge' => __( 'Quality', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_models',
|
||||
'default' => PRAUTOBLOGGER_DEFAULT_EDITOR_MODEL,
|
||||
'description' => __( 'Used for the chief editor review pass.', 'prautoblogger' ),
|
||||
'badge' => __( 'Quality', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Content ─────────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_niche_description',
|
||||
'label' => __( 'Niche Description', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_niche_description',
|
||||
'label' => __( 'Niche Description', 'prautoblogger' ),
|
||||
'type' => 'textarea',
|
||||
'section' => 'autoblogger_content',
|
||||
'description' => __( 'Describe your site\'s niche. Guides content analysis and generation.', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_content',
|
||||
'description' => __( 'Describe your site\'s niche. Guides content analysis and generation.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_tone',
|
||||
'label' => __( 'Content Tone', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_tone',
|
||||
'label' => __( 'Content Tone', 'prautoblogger' ),
|
||||
'type' => 'select',
|
||||
'section' => 'autoblogger_content',
|
||||
'section' => 'prautoblogger_content',
|
||||
'default' => 'informational',
|
||||
'options' => [
|
||||
'informational' => __( 'Informational', 'autoblogger' ),
|
||||
'conversational' => __( 'Conversational', 'autoblogger' ),
|
||||
'professional' => __( 'Professional', 'autoblogger' ),
|
||||
'casual' => __( 'Casual', 'autoblogger' ),
|
||||
'authoritative' => __( 'Authoritative', 'autoblogger' ),
|
||||
'informational' => __( 'Informational', 'prautoblogger' ),
|
||||
'conversational' => __( 'Conversational', 'prautoblogger' ),
|
||||
'professional' => __( 'Professional', 'prautoblogger' ),
|
||||
'casual' => __( 'Casual', 'prautoblogger' ),
|
||||
'authoritative' => __( 'Authoritative', 'prautoblogger' ),
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_writing_pipeline',
|
||||
'label' => __( 'Writing Pipeline', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_writing_pipeline',
|
||||
'label' => __( 'Writing Pipeline', 'prautoblogger' ),
|
||||
'type' => 'select',
|
||||
'section' => 'autoblogger_content',
|
||||
'section' => 'prautoblogger_content',
|
||||
'default' => 'multi_step',
|
||||
'options' => [
|
||||
'multi_step' => __( 'Multi-step (outline → draft → polish)', 'autoblogger' ),
|
||||
'single_pass' => __( 'Single-pass (one LLM call)', 'autoblogger' ),
|
||||
'multi_step' => __( 'Multi-step (outline → draft → polish)', 'prautoblogger' ),
|
||||
'single_pass' => __( 'Single-pass (one LLM call)', 'prautoblogger' ),
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_min_word_count',
|
||||
'label' => __( 'Min Word Count', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_min_word_count',
|
||||
'label' => __( 'Min Word Count', 'prautoblogger' ),
|
||||
'type' => 'number',
|
||||
'section' => 'autoblogger_content',
|
||||
'section' => 'prautoblogger_content',
|
||||
'default' => 800,
|
||||
'min' => 200,
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_max_word_count',
|
||||
'label' => __( 'Max Word Count', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_max_word_count',
|
||||
'label' => __( 'Max Word Count', 'prautoblogger' ),
|
||||
'type' => 'number',
|
||||
'section' => 'autoblogger_content',
|
||||
'section' => 'prautoblogger_content',
|
||||
'default' => 2000,
|
||||
'min' => 500,
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_topic_exclusions',
|
||||
'label' => __( 'Topic Exclusions', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_topic_exclusions',
|
||||
'label' => __( 'Topic Exclusions', 'prautoblogger' ),
|
||||
'type' => 'textarea',
|
||||
'section' => 'autoblogger_content',
|
||||
'description' => __( 'Comma-separated topics to never write about.', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_content',
|
||||
'description' => __( 'Comma-separated topics to never write about.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Sources ─────────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_target_subreddits',
|
||||
'label' => __( 'Target Subreddits', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_target_subreddits',
|
||||
'label' => __( 'Target Subreddits', 'prautoblogger' ),
|
||||
'type' => 'textarea',
|
||||
'section' => 'autoblogger_sources',
|
||||
'description' => __( 'Comma-separated, without r/. E.g.: peptides, Nootropics, biohackers', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_sources',
|
||||
'description' => __( 'Comma-separated, without r/. E.g.: peptides, Nootropics, biohackers', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_enabled_sources',
|
||||
'label' => __( 'Enabled Sources', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_enabled_sources',
|
||||
'label' => __( 'Enabled Sources', 'prautoblogger' ),
|
||||
'type' => 'checkboxes',
|
||||
'section' => 'autoblogger_sources',
|
||||
'section' => 'prautoblogger_sources',
|
||||
'options' => [
|
||||
'reddit' => __( 'Reddit', 'autoblogger' ),
|
||||
'tiktok' => __( 'TikTok (coming soon)', 'autoblogger' ),
|
||||
'instagram' => __( 'Instagram (coming soon)', 'autoblogger' ),
|
||||
'youtube' => __( 'YouTube (coming soon)', 'autoblogger' ),
|
||||
'reddit' => __( 'Reddit', 'prautoblogger' ),
|
||||
'tiktok' => __( 'TikTok (coming soon)', 'prautoblogger' ),
|
||||
'instagram' => __( 'Instagram (coming soon)', 'prautoblogger' ),
|
||||
'youtube' => __( 'YouTube (coming soon)', 'prautoblogger' ),
|
||||
],
|
||||
'default' => '["reddit"]',
|
||||
'description' => __( 'Select which platforms to monitor for topics.', 'autoblogger' ),
|
||||
'description' => __( 'Select which platforms to monitor for topics.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Schedule & Budget ───────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_daily_article_target',
|
||||
'label' => __( 'Articles per Day', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_daily_article_target',
|
||||
'label' => __( 'Articles per Day', 'prautoblogger' ),
|
||||
'type' => 'number',
|
||||
'section' => 'autoblogger_schedule',
|
||||
'section' => 'prautoblogger_schedule',
|
||||
'default' => 1,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_schedule_time',
|
||||
'label' => __( 'Generation Time', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_schedule_time',
|
||||
'label' => __( 'Generation Time', 'prautoblogger' ),
|
||||
'type' => 'time',
|
||||
'section' => 'autoblogger_schedule',
|
||||
'section' => 'prautoblogger_schedule',
|
||||
'default' => '03:00',
|
||||
'description' => __( 'Daily generation runs at this time (server timezone).', 'autoblogger' ),
|
||||
'description' => __( 'Daily generation runs at this time (server timezone).', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_monthly_budget_usd',
|
||||
'label' => __( 'Monthly Budget (USD)', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_monthly_budget_usd',
|
||||
'label' => __( 'Monthly Budget (USD)', 'prautoblogger' ),
|
||||
'type' => 'number',
|
||||
'section' => 'autoblogger_schedule',
|
||||
'section' => 'prautoblogger_schedule',
|
||||
'default' => 50,
|
||||
'min' => 0,
|
||||
'step' => '0.01',
|
||||
'description' => __( 'Hard stop when reached. 0 = unlimited.', 'autoblogger' ),
|
||||
'description' => __( 'Hard stop when reached. 0 = unlimited.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Publishing ──────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_auto_publish',
|
||||
'label' => __( 'Auto-Publish', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_auto_publish',
|
||||
'label' => __( 'Auto-Publish', 'prautoblogger' ),
|
||||
'type' => 'toggle',
|
||||
'section' => 'autoblogger_publishing',
|
||||
'section' => 'prautoblogger_publishing',
|
||||
'default' => '0',
|
||||
'description' => __( 'Automatically publish editor-approved posts. When off, all posts go to the Review Queue as drafts.', 'autoblogger' ),
|
||||
'description' => __( 'Automatically publish editor-approved posts. When off, all posts go to the Review Queue as drafts.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_default_author',
|
||||
'label' => __( 'Default Author', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_default_author',
|
||||
'label' => __( 'Default Author', 'prautoblogger' ),
|
||||
'type' => 'author_select',
|
||||
'section' => 'autoblogger_publishing',
|
||||
'section' => 'prautoblogger_publishing',
|
||||
'default' => 0,
|
||||
'description' => __( 'WordPress user assigned as author of generated posts.', 'autoblogger' ),
|
||||
'description' => __( 'WordPress user assigned as author of generated posts.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_default_category',
|
||||
'label' => __( 'Default Category', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_default_category',
|
||||
'label' => __( 'Default Category', 'prautoblogger' ),
|
||||
'type' => 'category_select',
|
||||
'section' => 'autoblogger_publishing',
|
||||
'section' => 'prautoblogger_publishing',
|
||||
'default' => 0,
|
||||
'description' => __( 'Fallback category for generated posts.', 'autoblogger' ),
|
||||
'description' => __( 'Fallback category for generated posts.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Logging ─────────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_log_level',
|
||||
'label' => __( 'Log Level', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_log_level',
|
||||
'label' => __( 'Log Level', 'prautoblogger' ),
|
||||
'type' => 'select',
|
||||
'section' => 'autoblogger_publishing',
|
||||
'section' => 'prautoblogger_publishing',
|
||||
'default' => 'info',
|
||||
'options' => [
|
||||
'error' => __( 'Error — only failures', 'autoblogger' ),
|
||||
'warning' => __( 'Warning — errors + warnings', 'autoblogger' ),
|
||||
'info' => __( 'Info — key events (recommended)', 'autoblogger' ),
|
||||
'debug' => __( 'Debug — everything (verbose)', 'autoblogger' ),
|
||||
'error' => __( 'Error — only failures', 'prautoblogger' ),
|
||||
'warning' => __( 'Warning — errors + warnings', 'prautoblogger' ),
|
||||
'info' => __( 'Info — key events (recommended)', 'prautoblogger' ),
|
||||
'debug' => __( 'Debug — everything (verbose)', 'prautoblogger' ),
|
||||
],
|
||||
'description' => __( 'Controls detail level in the Activity Log.', 'autoblogger' ),
|
||||
'description' => __( 'Controls detail level in the Activity Log.', 'prautoblogger' ),
|
||||
],
|
||||
|
||||
// ── Analytics ───────────────────────────────────────────────
|
||||
[
|
||||
'id' => 'autoblogger_ga4_property_id',
|
||||
'label' => __( 'GA4 Property ID', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_ga4_property_id',
|
||||
'label' => __( 'GA4 Property ID', 'prautoblogger' ),
|
||||
'type' => 'text',
|
||||
'section' => 'autoblogger_analytics',
|
||||
'description' => __( 'Format: properties/XXXXXXXXX. Leave blank to skip GA4.', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_analytics',
|
||||
'description' => __( 'Format: properties/XXXXXXXXX. Leave blank to skip GA4.', 'prautoblogger' ),
|
||||
],
|
||||
[
|
||||
'id' => 'autoblogger_ga4_credentials_json',
|
||||
'label' => __( 'Service Account JSON', 'autoblogger' ),
|
||||
'id' => 'prautoblogger_ga4_credentials_json',
|
||||
'label' => __( 'Service Account JSON', 'prautoblogger' ),
|
||||
'type' => 'password',
|
||||
'section' => 'autoblogger_analytics',
|
||||
'description' => __( 'Paste the full JSON key file for a service account with Analytics read access.', 'autoblogger' ),
|
||||
'section' => 'prautoblogger_analytics',
|
||||
'description' => __( 'Paste the full JSON key file for a service account with Analytics read access.', 'prautoblogger' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user