diff --git a/assets/styles.css b/assets/styles.css new file mode 100644 index 0000000..fd9287f --- /dev/null +++ b/assets/styles.css @@ -0,0 +1,6 @@ +.wprc-grid { display:grid; grid-template-columns:repeat(auto-fill, minmax(160px,1fr)); gap:16px; } +.wprc-card { border:1px solid #e5e7eb; border-radius:12px; overflow:hidden; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,.04); } +.wprc-card img { width:100%; height:auto; display:block; } +.wprc-meta { padding:10px; } +.wprc-sub { color:#6b7280; font-size:12px; margin-top:4px; } +.wprc-pre { white-space:pre-wrap; font-size:12px; background:#f8fafc; padding:10px; border-radius:8px; } diff --git a/includes/class-wprc-fetcher.php b/includes/class-wprc-fetcher.php new file mode 100644 index 0000000..a764089 --- /dev/null +++ b/includes/class-wprc-fetcher.php @@ -0,0 +1,56 @@ + 0) { + $cached = get_transient($cache_key); + if ($cached !== false) return $cached; + } + + $headers = ['Accept' => 'application/json']; + if ($token) $headers['Authorization'] = 'Bearer ' . $token; + + $resp = wp_remote_get($url, [ + 'headers' => $headers, + 'timeout' => 20, + ]); + + if (is_wp_error($resp)) { + return ['error' => $resp->get_error_message(), 'status' => 0]; + } + + $code = wp_remote_retrieve_response_code($resp); + $body = wp_remote_retrieve_body($resp); + $data = json_decode($body, true); + + $result = ['status' => $code, 'url' => $url, 'data' => $data]; + if ($cache_minutes > 0 && $code >= 200 && $code < 300) { + set_transient($cache_key, $result, $cache_minutes * MINUTE_IN_SECONDS); + } + return $result; + } +} diff --git a/includes/class-wprc-rest.php b/includes/class-wprc-rest.php new file mode 100644 index 0000000..19a10ea --- /dev/null +++ b/includes/class-wprc-rest.php @@ -0,0 +1,27 @@ + 'GET', + 'callback' => [__CLASS__, 'handle_fetch'], + 'permission_callback' => '__return_true', // read-only, but throttling may be added later + 'args' => [ + 'query' => ['type' => 'string', 'required' => false], + ], + ]); + } + + public static function handle_fetch(\WP_REST_Request $req) { + $query = $req->get_param('query') ?: ''; + $res = Fetcher::fetch(['query' => $query]); + return rest_ensure_response($res); + } +} diff --git a/includes/class-wprc-settings.php b/includes/class-wprc-settings.php new file mode 100644 index 0000000..3c2bca5 --- /dev/null +++ b/includes/class-wprc-settings.php @@ -0,0 +1,78 @@ + [__CLASS__, 'sanitize']]); + + add_settings_section('wprc_main', 'API Settings', function () { + echo '
Set your remote API details. Data is fetched server-side.
'; + }, 'wprc'); + + add_settings_field('base_url', 'Base URL', [__CLASS__, 'field_text'], 'wprc', 'wprc_main', ['key' => 'base_url', 'placeholder' => 'https://api.themoviedb.org/3']); + add_settings_field('endpoint_path', 'Endpoint Path', [__CLASS__, 'field_text'], 'wprc', 'wprc_main', ['key' => 'endpoint_path', 'placeholder' => '/discover/movie']); + add_settings_field('bearer_token', 'Bearer Token', [__CLASS__, 'field_password'], 'wprc', 'wprc_main', ['key' => 'bearer_token']); + add_settings_field('default_query', 'Default Query (key=value&key2=value2)', [__CLASS__, 'field_text'], 'wprc', 'wprc_main', ['key' => 'default_query', 'placeholder' => 'sort_by=popularity.desc']); + add_settings_field('cache_minutes', 'Cache Minutes', [__CLASS__, 'field_number'], 'wprc', 'wprc_main', ['key' => 'cache_minutes', 'placeholder' => '10']); + } + + public static function sanitize($opts) { + $clean = []; + $clean['base_url'] = isset($opts['base_url']) ? esc_url_raw(trim($opts['base_url'])) : ''; + $clean['endpoint_path'] = isset($opts['endpoint_path']) ? sanitize_text_field(trim($opts['endpoint_path'])) : ''; + $clean['bearer_token'] = isset($opts['bearer_token']) ? trim($opts['bearer_token']) : ''; + $clean['default_query'] = isset($opts['default_query']) ? sanitize_text_field(trim($opts['default_query'])) : ''; + $clean['cache_minutes'] = isset($opts['cache_minutes']) ? max(0, intval($opts['cache_minutes'])) : 0; + return $clean; + } + + public static function render_page() { + if (!current_user_can('manage_options')) return; + ?> +Tip: The token is stored in the database (options table). Don’t commit it to Git.
+⚠️ Error: ' . esc_html($res['error']) . '
'; + } + if (empty($res['data'])) { + return 'No data.
'; + } + + wp_enqueue_style('wprc-styles'); + + // Very simple renderer for TMDB "results" + $html = '' . esc_html(print_r($items, true)) . ''; + } + + $html .= '