style(phpcs): autofix WordPress-Core violations via phpcbf

Run phpcbf --standard=WordPress-Core across includes/, prautoblogger.php,
and uninstall.php. Fixed 1,362 formatting violations in 75 files:
  - Short array syntax: [] → array()
  - Line breaking for long function calls
  - Consistent indentation
  - Function call parameter alignment

No logic changes; purely mechanical formatting.
This commit is contained in:
peptiderepo
2026-04-23 02:42:48 +00:00
parent 7cd65b145f
commit f3eacd0d8d
75 changed files with 2148 additions and 1412 deletions

View File

@@ -45,7 +45,7 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
if ( '' === trim( $prompt ) ) {
PRAutoBlogger_Logger::instance()->warning( 'LLM Research prompt is empty. Skipping.', 'llm-research' );
return [];
return array();
}
$system_prompt = $this->build_system_prompt();
@@ -53,16 +53,22 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
$llm = new PRAutoBlogger_OpenRouter_Provider();
$response = $llm->send_chat_completion(
[
[ 'role' => 'system', 'content' => $system_prompt ],
[ 'role' => 'user', 'content' => $user_prompt ],
],
array(
array(
'role' => 'system',
'content' => $system_prompt,
),
array(
'role' => 'user',
'content' => $user_prompt,
),
),
$model,
[
array(
'temperature' => 0.7,
'max_tokens' => 8000,
'response_format' => [ 'type' => 'json_object' ],
]
'response_format' => array( 'type' => 'json_object' ),
)
);
// Use the pipeline's cost tracker if provided (for run_id tagging),
@@ -102,11 +108,11 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
* @return array{remaining: int, limit: int, resets_at: string}
*/
public function get_rate_limit_status(): array {
return [
return array(
'remaining' => 999,
'limit' => 999,
'resets_at' => '',
];
'resets_at' => '',
);
}
/**
@@ -133,7 +139,7 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
. "Respond with valid JSON only (no preamble, no markdown fences):\n"
. '{"findings": [{"title": "string", "content": "string (2-3 paragraphs)", '
. '"relevance_score": 0-100, "category": "question|trend|comparison|guide|misconception|safety"}]}' . "\n\n"
. "Generate 8-12 findings. Prioritize depth over breadth. Avoid generic or surface-level topics.";
. 'Generate 8-12 findings. Prioritize depth over breadth. Avoid generic or surface-level topics.';
}
/**
@@ -164,16 +170,16 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
. mb_substr( $content, 0, 500 ),
'llm-research'
);
return [];
return array();
}
$items = [];
$items = array();
$run_date = gmdate( 'Y-m-d' );
foreach ( $data['findings'] as $index => $finding ) {
$title = sanitize_text_field( $finding['title'] ?? '' );
$body = sanitize_textarea_field( $finding['content'] ?? '' );
$score = min( 100, max( 0, (int) ( $finding['relevance_score'] ?? 50 ) ) );
$title = sanitize_text_field( $finding['title'] ?? '' );
$body = sanitize_textarea_field( $finding['content'] ?? '' );
$score = min( 100, max( 0, (int) ( $finding['relevance_score'] ?? 50 ) ) );
$category = sanitize_text_field( $finding['category'] ?? 'guide' );
if ( '' === $title || '' === $body ) {
@@ -184,23 +190,25 @@ class PRAutoBlogger_LLM_Research_Provider implements PRAutoBlogger_Source_Provid
// but a new day produces fresh entries.
$source_id = 'llm_' . $run_date . '_' . $index;
$items[] = new PRAutoBlogger_Source_Data( [
'source_type' => self::SOURCE_TYPE,
'source_id' => $source_id,
'subreddit' => null,
'title' => $title,
'content' => $body,
'author' => $model,
'score' => $score,
'comment_count' => 0,
'permalink' => null,
'collected_at' => current_time( 'mysql' ),
'metadata' => [
'category' => $category,
'data_source' => 'llm_research',
'model' => $model,
],
] );
$items[] = new PRAutoBlogger_Source_Data(
array(
'source_type' => self::SOURCE_TYPE,
'source_id' => $source_id,
'subreddit' => null,
'title' => $title,
'content' => $body,
'author' => $model,
'score' => $score,
'comment_count' => 0,
'permalink' => null,
'collected_at' => current_time( 'mysql' ),
'metadata' => array(
'category' => $category,
'data_source' => 'llm_research',
'model' => $model,
),
)
);
}
PRAutoBlogger_Logger::instance()->info(

View File

@@ -41,7 +41,7 @@ class PRAutoBlogger_OpenRouter_Embedding_Provider {
*/
public function get_embeddings( array $texts, string $model = '' ): array {
if ( empty( $texts ) ) {
return [];
return array();
}
$api_key = $this->get_api_key();
@@ -64,14 +64,16 @@ class PRAutoBlogger_OpenRouter_Embedding_Provider {
try {
$response = wp_remote_post(
$base_url . '/embeddings',
[
array(
'timeout' => 30,
'headers' => $request_headers,
'body' => wp_json_encode( [
'model' => $model,
'input' => array_values( $texts ),
] ),
]
'body' => wp_json_encode(
array(
'model' => $model,
'input' => array_values( $texts ),
)
),
)
);
if ( is_wp_error( $response ) ) {
@@ -149,11 +151,14 @@ class PRAutoBlogger_OpenRouter_Embedding_Provider {
}
// Sort by index to match input order (API may return out of order).
usort( $body['data'], static function ( array $a, array $b ): int {
return ( $a['index'] ?? 0 ) <=> ( $b['index'] ?? 0 );
} );
usort(
$body['data'],
static function ( array $a, array $b ): int {
return ( $a['index'] ?? 0 ) <=> ( $b['index'] ?? 0 );
}
);
$embeddings = [];
$embeddings = array();
foreach ( $body['data'] as $item ) {
if ( ! isset( $item['embedding'] ) || ! is_array( $item['embedding'] ) ) {
throw new \RuntimeException( 'Embedding item missing "embedding" array.' );

View File

@@ -73,7 +73,7 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
*/
public function execute( array $requests ): array {
if ( empty( $requests ) ) {
return [];
return array();
}
$api_key = $this->support->get_api_key();
@@ -86,15 +86,15 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
);
// Convert associative headers to curl-style indexed array.
$curl_headers = [];
$curl_headers = array();
foreach ( $headers as $name => $value ) {
$curl_headers[] = $name . ': ' . $value;
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_multi_init
$multi_handle = curl_multi_init();
$handles = [];
$start_times = [];
$handles = array();
$start_times = array();
foreach ( $requests as $key => $req ) {
$model = $this->pricing->resolve_model( (string) ( $req['options']['model'] ?? '' ) );
@@ -119,7 +119,11 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_multi_add_handle
curl_multi_add_handle( $multi_handle, $ch );
$handles[ $key ] = [ 'handle' => $ch, 'model' => $model, 'req' => $req ];
$handles[ $key ] = array(
'handle' => $ch,
'model' => $model,
'req' => $req,
);
$start_times[ $key ] = microtime( true );
}
@@ -127,7 +131,7 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
$this->run_multi( $multi_handle );
// Collect results.
$results = [];
$results = array();
foreach ( $handles as $key => $entry ) {
$results[ $key ] = $this->collect_result(
(string) $key,
@@ -200,7 +204,7 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
$detail
);
PRAutoBlogger_Logger::instance()->error( $msg, 'openrouter-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_getinfo
@@ -216,7 +220,7 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
substr( $raw, 0, 300 )
);
PRAutoBlogger_Logger::instance()->error( $msg, 'openrouter-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
try {
@@ -228,10 +232,10 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
$e->getMessage()
);
PRAutoBlogger_Logger::instance()->error( $msg, 'openrouter-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
return [
return array(
'bytes' => $image_bytes,
'mime_type' => 'image/png',
'width' => $req['width'],
@@ -240,7 +244,7 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
'seed' => null,
'cost_usd' => $this->pricing->estimate_cost( $req['width'], $req['height'], $model ),
'latency_ms' => $latency_ms,
];
);
}
/**
@@ -259,17 +263,45 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
$target = $height > 0 ? (float) $width / (float) $height : 1.0;
// Snap to nearest standard aspect ratio.
$aspects = [
[ 'w' => 1, 'h' => 1, 'r' => 1.0 ],
[ 'w' => 3, 'h' => 2, 'r' => 1.5 ],
[ 'w' => 2, 'h' => 3, 'r' => 0.6667 ],
[ 'w' => 4, 'h' => 3, 'r' => 1.3333 ],
[ 'w' => 3, 'h' => 4, 'r' => 0.75 ],
[ 'w' => 16, 'h' => 9, 'r' => 1.7778 ],
[ 'w' => 9, 'h' => 16, 'r' => 0.5625 ],
];
$best = $aspects[0];
$best_d = abs( $target - $best['r'] );
$aspects = array(
array(
'w' => 1,
'h' => 1,
'r' => 1.0,
),
array(
'w' => 3,
'h' => 2,
'r' => 1.5,
),
array(
'w' => 2,
'h' => 3,
'r' => 0.6667,
),
array(
'w' => 4,
'h' => 3,
'r' => 1.3333,
),
array(
'w' => 3,
'h' => 4,
'r' => 0.75,
),
array(
'w' => 16,
'h' => 9,
'r' => 1.7778,
),
array(
'w' => 9,
'h' => 16,
'r' => 0.5625,
),
);
$best = $aspects[0];
$best_d = abs( $target - $best['r'] );
foreach ( $aspects as $c ) {
$d = abs( $target - $c['r'] );
if ( $d < $best_d ) {
@@ -279,16 +311,16 @@ class PRAutoBlogger_OpenRouter_Image_Batch {
}
$aspect = $best['w'] . ':' . $best['h'];
return [
return array(
'model' => $model,
'messages' => [
[
'messages' => array(
array(
'role' => 'user',
'content' => 'Generate an image: ' . $prompt,
],
],
'modalities' => [ 'image', 'text' ],
'image_config' => [ 'aspect_ratio' => $aspect ],
];
),
),
'modalities' => array( 'image', 'text' ),
'image_config' => array( 'aspect_ratio' => $aspect ),
);
}
}

View File

@@ -22,13 +22,13 @@ class PRAutoBlogger_OpenRouter_Image_Pricing {
*
* @var array<string, float>
*/
private const COST_PER_IMAGE = [
'google/gemini-2.5-flash-image' => 0.005,
'google/gemini-3.1-flash-image-preview' => 0.008,
'google/gemini-3-pro-image-preview' => 0.03,
'openai/gpt-5-image-mini' => 0.02,
'openai/gpt-5-image' => 0.08,
];
private const COST_PER_IMAGE = array(
'google/gemini-2.5-flash-image' => 0.005,
'google/gemini-3.1-flash-image-preview' => 0.008,
'google/gemini-3-pro-image-preview' => 0.03,
'openai/gpt-5-image-mini' => 0.02,
'openai/gpt-5-image' => 0.08,
);
/**
* Resolve the model identifier from a hint, falling back to site option,

View File

@@ -43,7 +43,7 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
*
* Retries 5xx/429 with exponential backoff; 4xx (except 429) fail immediately.
*/
public function generate_image( string $prompt, int $width, int $height, array $options = [] ): array {
public function generate_image( string $prompt, int $width, int $height, array $options = array() ): array {
$this->assert_valid_dimensions( $width, $height );
$prompt = trim( $prompt );
if ( '' === $prompt ) {
@@ -74,11 +74,14 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
try {
for ( $attempt = 1; $attempt <= PRAUTOBLOGGER_MAX_RETRIES; $attempt++ ) {
$response = wp_remote_post( $url, [
'timeout' => PRAUTOBLOGGER_API_TIMEOUT_SECONDS,
'headers' => $headers,
'body' => wp_json_encode( $body ),
] );
$response = wp_remote_post(
$url,
array(
'timeout' => PRAUTOBLOGGER_API_TIMEOUT_SECONDS,
'headers' => $headers,
'body' => wp_json_encode( $body ),
)
);
if ( is_wp_error( $response ) ) {
$last_error = $response->get_error_message();
@@ -116,7 +119,7 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
$image_bytes = $this->support->extract_image_bytes( $raw );
return [
return array(
'bytes' => $image_bytes,
'mime_type' => 'image/png',
'width' => $width,
@@ -125,7 +128,7 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
'seed' => null,
'cost_usd' => $this->pricing->estimate_cost( $width, $height, $model ),
'latency_ms' => (int) ( ( microtime( true ) - $started_at ) * 1000 ),
];
);
}
} finally {
remove_action( 'http_api_curl', $curl_filter, 99 );
@@ -176,7 +179,7 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
}
/** {@inheritDoc} */
public function estimate_cost( int $width, int $height, array $options = [] ): float {
public function estimate_cost( int $width, int $height, array $options = array() ): float {
$model = $this->pricing->resolve_model( (string) ( $options['model'] ?? '' ) );
return $this->pricing->estimate_cost( $width, $height, $model );
}
@@ -191,32 +194,41 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
try {
$api_key = $this->support->get_api_key();
} catch ( \RuntimeException $e ) {
return [ 'status' => 'error', 'message' => $e->getMessage() ];
return array(
'status' => 'error',
'message' => $e->getMessage(),
);
}
$response = wp_remote_get( 'https://openrouter.ai/api/v1/auth/key', [
'timeout' => 15,
'headers' => [ 'Authorization' => 'Bearer ' . $api_key ],
] );
$response = wp_remote_get(
'https://openrouter.ai/api/v1/auth/key',
array(
'timeout' => 15,
'headers' => array( 'Authorization' => 'Bearer ' . $api_key ),
)
);
if ( is_wp_error( $response ) ) {
return [
return array(
'status' => 'error',
'message' => __( 'Could not reach OpenRouter API.', 'prautoblogger' ),
'debug' => $response->get_error_message(),
];
);
}
$status = (int) wp_remote_retrieve_response_code( $response );
if ( 200 === $status ) {
return [ 'status' => 'ok', 'message' => __( 'OpenRouter API key valid.', 'prautoblogger' ) ];
return array(
'status' => 'ok',
'message' => __( 'OpenRouter API key valid.', 'prautoblogger' ),
);
}
return [
return array(
'status' => 'error',
'message' => sprintf( __( 'OpenRouter returned HTTP %d.', 'prautoblogger' ), $status ),
'debug' => substr( (string) wp_remote_retrieve_body( $response ), 0, 200 ),
];
);
}
/**
@@ -224,34 +236,62 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
*
* @var array<int, array{w: int, h: int, ratio: float}>
*/
private const STANDARD_ASPECTS = [
[ 'w' => 1, 'h' => 1, 'ratio' => 1.0 ],
[ 'w' => 3, 'h' => 2, 'ratio' => 1.5 ],
[ 'w' => 2, 'h' => 3, 'ratio' => 0.6667 ],
[ 'w' => 4, 'h' => 3, 'ratio' => 1.3333 ],
[ 'w' => 3, 'h' => 4, 'ratio' => 0.75 ],
[ 'w' => 16, 'h' => 9, 'ratio' => 1.7778 ],
[ 'w' => 9, 'h' => 16, 'ratio' => 0.5625 ],
];
private const STANDARD_ASPECTS = array(
array(
'w' => 1,
'h' => 1,
'ratio' => 1.0,
),
array(
'w' => 3,
'h' => 2,
'ratio' => 1.5,
),
array(
'w' => 2,
'h' => 3,
'ratio' => 0.6667,
),
array(
'w' => 4,
'h' => 3,
'ratio' => 1.3333,
),
array(
'w' => 3,
'h' => 4,
'ratio' => 0.75,
),
array(
'w' => 16,
'h' => 9,
'ratio' => 1.7778,
),
array(
'w' => 9,
'h' => 16,
'ratio' => 0.5625,
),
);
private function build_request_body( string $prompt, int $width, int $height, string $model ): array {
$aspect = $this->snap_aspect_ratio( $width, $height );
return [
'model' => $model,
'messages' => [
[
return array(
'model' => $model,
'messages' => array(
array(
'role' => 'user',
'content' => 'Generate an image: ' . $prompt,
],
],
),
),
// Use ["image", "text"] — some providers (Gemini) require both
// modalities even when we only want the image output.
'modalities' => [ 'image', 'text' ],
'image_config' => [
'modalities' => array( 'image', 'text' ),
'image_config' => array(
'aspect_ratio' => $aspect,
],
];
),
);
}
/**
@@ -262,9 +302,9 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
* @return string Aspect ratio string like "16:9".
*/
private function snap_aspect_ratio( int $width, int $height ): string {
$target = $height > 0 ? (float) $width / (float) $height : 1.0;
$best = self::STANDARD_ASPECTS[0];
$best_d = abs( $target - $best['ratio'] );
$target = $height > 0 ? (float) $width / (float) $height : 1.0;
$best = self::STANDARD_ASPECTS[0];
$best_d = abs( $target - $best['ratio'] );
foreach ( self::STANDARD_ASPECTS as $candidate ) {
$d = abs( $target - $candidate['ratio'] );
@@ -292,7 +332,10 @@ class PRAutoBlogger_OpenRouter_Image_Provider implements PRAutoBlogger_Image_Pro
throw new \InvalidArgumentException(
sprintf(
esc_html__( 'Image dimensions %1$dx%2$d outside supported range (%3$d–%4$d px).', 'prautoblogger' ),
$width, $height, self::MIN_DIMENSION_PX, self::MAX_DIMENSION_PX
$width,
$height,
self::MIN_DIMENSION_PX,
self::MAX_DIMENSION_PX
)
);
}

View File

@@ -69,7 +69,7 @@ class PRAutoBlogger_OpenRouter_Image_Support {
);
}
$images = $decoded['choices'][0]['message']['images'] ?? [];
$images = $decoded['choices'][0]['message']['images'] ?? array();
if ( empty( $images ) ) {
throw new \RuntimeException(
esc_html__( 'OpenRouter response contained no images.', 'prautoblogger' )

View File

@@ -21,15 +21,36 @@ class PRAutoBlogger_OpenRouter_Pricing {
*
* @var array<string, array{prompt: float, completion: float}>
*/
private const MODEL_PRICING = [
'anthropic/claude-3.5-haiku' => [ 'prompt' => 0.80, 'completion' => 4.00 ],
'anthropic/claude-sonnet-4' => [ 'prompt' => 3.00, 'completion' => 15.00 ],
'anthropic/claude-opus-4' => [ 'prompt' => 15.00, 'completion' => 75.00 ],
'openai/gpt-4o' => [ 'prompt' => 2.50, 'completion' => 10.00 ],
'openai/gpt-4o-mini' => [ 'prompt' => 0.15, 'completion' => 0.60 ],
'google/gemini-2.0-flash' => [ 'prompt' => 0.10, 'completion' => 0.40 ],
'meta-llama/llama-3.3-70b' => [ 'prompt' => 0.40, 'completion' => 0.40 ],
];
private const MODEL_PRICING = array(
'anthropic/claude-3.5-haiku' => array(
'prompt' => 0.80,
'completion' => 4.00,
),
'anthropic/claude-sonnet-4' => array(
'prompt' => 3.00,
'completion' => 15.00,
),
'anthropic/claude-opus-4' => array(
'prompt' => 15.00,
'completion' => 75.00,
),
'openai/gpt-4o' => array(
'prompt' => 2.50,
'completion' => 10.00,
),
'openai/gpt-4o-mini' => array(
'prompt' => 0.15,
'completion' => 0.60,
),
'google/gemini-2.0-flash' => array(
'prompt' => 0.10,
'completion' => 0.40,
),
'meta-llama/llama-3.3-70b' => array(
'prompt' => 0.40,
'completion' => 0.40,
),
);
/**
* Get available models from OpenRouter's /models endpoint.
@@ -48,7 +69,7 @@ class PRAutoBlogger_OpenRouter_Pricing {
$api_key = $this->get_api_key();
if ( '' === $api_key ) {
return [];
return array();
}
// Belt-and-suspenders: inject Authorization at cURL level (see OpenRouter_Provider).
@@ -58,43 +79,47 @@ class PRAutoBlogger_OpenRouter_Pricing {
return;
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
curl_setopt( $handle, CURLOPT_HTTPHEADER, [
'Authorization: ' . $auth_header_value,
] );
curl_setopt(
$handle,
CURLOPT_HTTPHEADER,
array(
'Authorization: ' . $auth_header_value,
)
);
};
add_action( 'http_api_curl', $curl_auth_filter_mod, 99, 3 );
$response = wp_remote_get(
'https://openrouter.ai/api/v1/models',
[
array(
'timeout' => 30,
'headers' => [
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
],
]
),
)
);
remove_action( 'http_api_curl', $curl_auth_filter_mod, 99 );
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
PRAutoBlogger_Logger::instance()->warning( 'Failed to fetch OpenRouter models list.', 'openrouter' );
return [];
return array();
}
$data = json_decode( wp_remote_retrieve_body( $response ), true );
$models = [];
$models = array();
if ( isset( $data['data'] ) && is_array( $data['data'] ) ) {
foreach ( $data['data'] as $model ) {
$models[] = [
$models[] = array(
'id' => $model['id'] ?? '',
'name' => $model['name'] ?? $model['id'] ?? '',
'context_length' => (int) ( $model['context_length'] ?? 0 ),
'pricing' => [
'pricing' => array(
'prompt' => (float) ( $model['pricing']['prompt'] ?? 0 ) * 1000000,
'completion' => (float) ( $model['pricing']['completion'] ?? 0 ) * 1000000,
],
];
),
);
}
}
@@ -135,7 +160,10 @@ class PRAutoBlogger_OpenRouter_Pricing {
if ( null === $pricing ) {
// Unknown model — use a conservative estimate.
PRAutoBlogger_Logger::instance()->warning( "Unknown model pricing for '{$model}'. Using conservative estimate.", 'openrouter' );
$pricing = [ 'prompt' => 10.0, 'completion' => 30.0 ];
$pricing = array(
'prompt' => 10.0,
'completion' => 30.0,
);
}
return ( $prompt_tokens * $pricing['prompt'] / 1000000 )

View File

@@ -50,7 +50,7 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
*
* @throws \RuntimeException On API error after retries exhausted.
*/
public function send_chat_completion( array $messages, string $model, array $options = [] ): array {
public function send_chat_completion( array $messages, string $model, array $options = array() ): array {
$api_key = $this->get_api_key();
if ( '' === $api_key ) {
throw new \RuntimeException(
@@ -74,10 +74,10 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
);
}
$body = [
$body = array(
'model' => $model,
'messages' => $messages,
];
);
if ( isset( $options['temperature'] ) ) {
$body['temperature'] = $options['temperature'];
@@ -93,10 +93,10 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
if ( isset( $options['reasoning'] ) ) {
$body['reasoning'] = $options['reasoning'];
} elseif ( '1' === get_option( 'prautoblogger_reasoning_enabled', '0' ) ) {
$body['reasoning'] = [
$body['reasoning'] = array(
'enabled' => true,
'effort' => get_option( 'prautoblogger_reasoning_effort', 'medium' ),
];
);
}
$last_error = '';
@@ -107,8 +107,8 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
$cache_ttl = $config->get_cache_ttl_seconds();
$via_gateway = $config->is_via_gateway();
$builder = new PRAutoBlogger_OpenRouter_Request_Builder();
$request_headers = $builder->build_headers( $api_key, $via_gateway, $cache_ttl );
$builder = new PRAutoBlogger_OpenRouter_Request_Builder();
$request_headers = $builder->build_headers( $api_key, $via_gateway, $cache_ttl );
$curl_auth_filter = $builder->register_curl_auth_filter( $request_headers, $base_host );
try {
@@ -117,11 +117,11 @@ class PRAutoBlogger_OpenRouter_Provider implements PRAutoBlogger_LLM_Provider_In
for ( $attempt = 1; $attempt <= PRAUTOBLOGGER_MAX_RETRIES; $attempt++ ) {
$response = wp_remote_post(
$base_url . '/chat/completions',
[
array(
'timeout' => PRAUTOBLOGGER_API_TIMEOUT_SECONDS,
'headers' => $request_headers,
'body' => wp_json_encode( $body ),
]
)
);
if ( is_wp_error( $response ) ) {

View File

@@ -29,12 +29,12 @@ class PRAutoBlogger_OpenRouter_Request_Builder {
* @return array<string, string> HTTP headers ready for wp_remote_post().
*/
public function build_headers( string $api_key, bool $via_gateway, int $cache_ttl ): array {
$headers = [
$headers = array(
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json',
'HTTP-Referer' => home_url(),
'X-Title' => 'PRAutoBlogger WordPress Plugin',
];
);
if ( $via_gateway && $cache_ttl > 0 ) {
$headers['cf-aig-cache-ttl'] = (string) $cache_ttl;
@@ -66,7 +66,7 @@ class PRAutoBlogger_OpenRouter_Request_Builder {
if ( '' === $base_host || false === strpos( (string) $url, $base_host ) ) {
return;
}
$curl_headers = [];
$curl_headers = array();
foreach ( $request_headers as $name => $value ) {
$curl_headers[] = $name . ': ' . $value;
}

View File

@@ -94,12 +94,12 @@ class PRAutoBlogger_OpenRouter_Response_Parser {
$content = '';
}
$usage = $data['usage'] ?? [];
$usage = $data['usage'] ?? array();
// Reasoning content lives alongside 'content' in the message object.
$reasoning_content = $data['choices'][0]['message']['reasoning'] ?? '';
return [
return array(
'content' => (string) $content,
'model' => $data['model'] ?? $model,
'prompt_tokens' => (int) ( $usage['prompt_tokens'] ?? 0 ),
@@ -108,7 +108,7 @@ class PRAutoBlogger_OpenRouter_Response_Parser {
'total_tokens' => (int) ( $usage['total_tokens'] ?? 0 ),
'finish_reason' => $data['choices'][0]['finish_reason'] ?? 'unknown',
'reasoning_content' => (string) $reasoning_content,
];
);
}
/**

View File

@@ -79,20 +79,24 @@ class PRAutoBlogger_OpenRouter_Validator {
return;
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_setopt
curl_setopt( $handle, CURLOPT_HTTPHEADER, [
'Authorization: ' . $auth_header_value,
] );
curl_setopt(
$handle,
CURLOPT_HTTPHEADER,
array(
'Authorization: ' . $auth_header_value,
)
);
};
add_action( 'http_api_curl', $curl_auth_filter_cred, 99, 3 );
$response = wp_remote_get(
$base_url . '/auth/key',
[
array(
'timeout' => self::TIMEOUT_SECONDS,
'headers' => [
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
],
]
),
)
);
remove_action( 'http_api_curl', $curl_auth_filter_cred, 99 );
@@ -115,10 +119,10 @@ class PRAutoBlogger_OpenRouter_Validator {
$status_code = wp_remote_retrieve_response_code( $response );
if ( 200 === $status_code ) {
return [
return array(
'status' => 'ok',
'message' => __( 'OpenRouter connected.', 'prautoblogger' ),
];
);
}
$body_raw = wp_remote_retrieve_body( $response );
@@ -143,10 +147,10 @@ class PRAutoBlogger_OpenRouter_Validator {
* @return array{status: string, message: string, debug: string}
*/
private function err( string $debug, string $message ): array {
return [
return array(
'status' => 'error',
'message' => $message,
'debug' => $debug,
];
);
}
}

View File

@@ -63,12 +63,12 @@ class PRAutoBlogger_Reddit_Availability {
$url = self::BASE_URL . '/r/all/hot.rss?limit=1';
$response = wp_remote_get(
$url,
[
array(
'timeout' => 10,
'headers' => [
'headers' => array(
'User-Agent' => self::USER_AGENT,
],
]
),
)
);
if ( is_wp_error( $response ) ) {
@@ -91,12 +91,12 @@ class PRAutoBlogger_Reddit_Availability {
$url = self::BASE_URL . '/r/all/hot.json?limit=1';
$response = wp_remote_get(
$url,
[
array(
'timeout' => 10,
'headers' => [
'headers' => array(
'User-Agent' => self::USER_AGENT,
],
]
),
)
);
if ( is_wp_error( $response ) ) {
@@ -121,11 +121,11 @@ class PRAutoBlogger_Reddit_Availability {
return $status;
}
return [
return array(
'remaining' => 10,
'limit' => 10,
'resets_at' => '',
];
);
}
/**
@@ -143,13 +143,13 @@ class PRAutoBlogger_Reddit_Availability {
public function api_get( string $url ): ?array {
$response = wp_remote_get(
$url,
[
array(
'timeout' => 30,
'headers' => [
'headers' => array(
'User-Agent' => self::USER_AGENT,
'Accept' => 'application/json',
],
]
),
)
);
if ( is_wp_error( $response ) ) {
@@ -168,11 +168,11 @@ class PRAutoBlogger_Reddit_Availability {
if ( '' !== $rate_remaining ) {
set_transient(
self::RATE_LIMIT_TRANSIENT,
[
array(
'remaining' => (int) $rate_remaining,
'limit' => (int) $rate_used + (int) $rate_remaining,
'resets_at' => gmdate( 'Y-m-d H:i:s', time() + (int) $rate_reset ),
],
),
120
);
}

View File

@@ -97,13 +97,13 @@ class PRAutoBlogger_Reddit_JSON_Client {
$response = wp_remote_get(
$url,
[
array(
'timeout' => self::TIMEOUT_SECONDS,
'headers' => [
'headers' => array(
'User-Agent' => self::USER_AGENT,
'Accept' => 'application/atom+xml, application/rss+xml',
],
]
),
)
);
if ( is_wp_error( $response ) ) {
@@ -111,7 +111,7 @@ class PRAutoBlogger_Reddit_JSON_Client {
'Reddit RSS GET failed: ' . $response->get_error_message(),
'reddit'
);
return [];
return array();
}
$status_code = wp_remote_retrieve_response_code( $response );
@@ -120,10 +120,10 @@ class PRAutoBlogger_Reddit_JSON_Client {
sprintf( 'Reddit RSS HTTP %d for r/%s', $status_code, $subreddit ),
'reddit'
);
return [];
return array();
}
$body = wp_remote_retrieve_body( $response );
$body = wp_remote_retrieve_body( $response );
$parser = new PRAutoBlogger_Reddit_RSS_Parser();
return $parser->parse( $body, $subreddit );
}
@@ -154,15 +154,15 @@ class PRAutoBlogger_Reddit_JSON_Client {
$response = $this->api_get( $url );
if ( null === $response || ! isset( $response['data']['children'] ) ) {
return [];
return array();
}
$posts = [];
$posts = array();
foreach ( $response['data']['children'] as $child ) {
if ( isset( $child['data'] ) ) {
$post = $child['data'];
$post = $child['data'];
$post['data_source'] = 'reddit_json';
$posts[] = $post;
$posts[] = $post;
}
}
@@ -197,10 +197,10 @@ class PRAutoBlogger_Reddit_JSON_Client {
// Comments endpoint returns [post_listing, comments_listing].
if ( ! is_array( $response ) || ! isset( $response[1]['data']['children'] ) ) {
return [];
return array();
}
$comments = [];
$comments = array();
foreach ( $response[1]['data']['children'] as $child ) {
// Filter out "more" type entries, keep only actual comments (kind=t1).
if ( isset( $child['data'] ) && 't1' === ( $child['kind'] ?? '' ) ) {

View File

@@ -47,7 +47,7 @@ class PRAutoBlogger_Reddit_Provider implements PRAutoBlogger_Source_Provider_Int
$comments_limit = $config['comments_per_post'] ?? 5;
$client = new PRAutoBlogger_Reddit_JSON_Client();
$collected = [];
$collected = array();
PRAutoBlogger_Logger::instance()->info(
sprintf(
@@ -72,26 +72,28 @@ class PRAutoBlogger_Reddit_Provider implements PRAutoBlogger_Source_Provider_Int
foreach ( $posts as $post ) {
$data_source = $post['data_source'] ?? 'reddit';
$collected[] = new PRAutoBlogger_Source_Data( [
'source_type' => 'reddit',
'source_id' => 't3_' . ( $post['id'] ?? '' ),
'subreddit' => $subreddit,
'title' => $post['title'] ?? '',
'content' => $post['selftext'] ?? '',
'author' => $post['author'] ?? '[deleted]',
'score' => (int) ( $post['score'] ?? 0 ),
'comment_count' => (int) ( $post['num_comments'] ?? 0 ),
'permalink' => 'https://reddit.com' . ( $post['permalink'] ?? '' ),
'collected_at' => current_time( 'mysql' ),
'metadata' => [
'post_type' => ( $post['is_self'] ?? false ) ? 'self' : 'link',
'flair' => $post['link_flair_text'] ?? null,
'created_utc' => $post['created_utc'] ?? null,
'upvote_ratio' => $post['upvote_ratio'] ?? null,
'is_original' => $post['is_original_content'] ?? false,
'data_source' => $data_source,
],
] );
$collected[] = new PRAutoBlogger_Source_Data(
array(
'source_type' => 'reddit',
'source_id' => 't3_' . ( $post['id'] ?? '' ),
'subreddit' => $subreddit,
'title' => $post['title'] ?? '',
'content' => $post['selftext'] ?? '',
'author' => $post['author'] ?? '[deleted]',
'score' => (int) ( $post['score'] ?? 0 ),
'comment_count' => (int) ( $post['num_comments'] ?? 0 ),
'permalink' => 'https://reddit.com' . ( $post['permalink'] ?? '' ),
'collected_at' => current_time( 'mysql' ),
'metadata' => array(
'post_type' => ( $post['is_self'] ?? false ) ? 'self' : 'link',
'flair' => $post['link_flair_text'] ?? null,
'created_utc' => $post['created_utc'] ?? null,
'upvote_ratio' => $post['upvote_ratio'] ?? null,
'is_original' => $post['is_original_content'] ?? false,
'data_source' => $data_source,
),
)
);
// Fetch comments for high-engagement posts via .json
// (comments are not available in RSS feeds).
@@ -100,25 +102,27 @@ class PRAutoBlogger_Reddit_Provider implements PRAutoBlogger_Source_Provider_Int
$comments = $client->fetch_comments( $subreddit, $post_id, $comments_limit );
foreach ( $comments as $comment ) {
$collected[] = new PRAutoBlogger_Source_Data( [
'source_type' => 'reddit',
'source_id' => 't1_' . ( $comment['id'] ?? '' ),
'subreddit' => $subreddit,
'title' => null,
'content' => $comment['body'] ?? '',
'author' => $comment['author'] ?? '[deleted]',
'score' => (int) ( $comment['score'] ?? 0 ),
'comment_count' => 0,
'permalink' => 'https://reddit.com' . ( $comment['permalink'] ?? '' ),
'collected_at' => current_time( 'mysql' ),
'metadata' => [
'parent_post_id' => 't3_' . $post_id,
'parent_title' => $post['title'] ?? '',
'is_comment' => true,
'created_utc' => $comment['created_utc'] ?? null,
'data_source' => 'reddit_json',
],
] );
$collected[] = new PRAutoBlogger_Source_Data(
array(
'source_type' => 'reddit',
'source_id' => 't1_' . ( $comment['id'] ?? '' ),
'subreddit' => $subreddit,
'title' => null,
'content' => $comment['body'] ?? '',
'author' => $comment['author'] ?? '[deleted]',
'score' => (int) ( $comment['score'] ?? 0 ),
'comment_count' => 0,
'permalink' => 'https://reddit.com' . ( $comment['permalink'] ?? '' ),
'collected_at' => current_time( 'mysql' ),
'metadata' => array(
'parent_post_id' => 't3_' . $post_id,
'parent_title' => $post['title'] ?? '',
'is_comment' => true,
'created_utc' => $comment['created_utc'] ?? null,
'data_source' => 'reddit_json',
),
)
);
}
}
}
@@ -184,6 +188,6 @@ class PRAutoBlogger_Reddit_Provider implements PRAutoBlogger_Source_Provider_Int
private function get_configured_subreddits(): array {
$json = get_option( 'prautoblogger_target_subreddits', '' );
$list = json_decode( $json, true );
return is_array( $list ) ? $list : [];
return is_array( $list ) ? $list : array();
}
}

View File

@@ -41,7 +41,7 @@ class PRAutoBlogger_Reddit_RSS_Parser {
if ( false === $feed ) {
PRAutoBlogger_Logger::instance()->error( 'Failed to parse Reddit RSS XML.', 'reddit' );
return [];
return array();
}
// Register the Atom namespace.
@@ -49,10 +49,10 @@ class PRAutoBlogger_Reddit_RSS_Parser {
$entries = $feed->xpath( '//atom:entry' );
if ( empty( $entries ) ) {
return [];
return array();
}
$posts = [];
$posts = array();
foreach ( $entries as $entry ) {
$post = $this->parse_entry( $entry, $subreddit );
if ( null !== $post ) {
@@ -118,7 +118,7 @@ class PRAutoBlogger_Reddit_RSS_Parser {
$permalink = $parsed['path'] ?? '';
}
return [
return array(
'id' => $post_id,
'title' => $title,
'selftext' => $content,
@@ -132,6 +132,6 @@ class PRAutoBlogger_Reddit_RSS_Parser {
'upvote_ratio' => null,
'is_original_content' => false,
'data_source' => 'reddit_rss',
];
);
}
}

View File

@@ -59,17 +59,17 @@ class PRAutoBlogger_Runware_Image_Batch {
*/
public function execute( array $requests ): array {
if ( empty( $requests ) ) {
return [];
return array();
}
$api_key = $this->support->get_api_key();
$round1 = $this->round_one_inference( $api_key, $requests );
$results = [];
$to_download = [];
$results = array();
$to_download = array();
foreach ( $round1 as $key => $entry ) {
if ( isset( $entry['error'] ) ) {
$results[ $key ] = [ 'error' => $entry['error'] ];
$results[ $key ] = array( 'error' => $entry['error'] );
continue;
}
$to_download[ $key ] = $entry;
@@ -82,10 +82,10 @@ class PRAutoBlogger_Runware_Image_Batch {
$bytes_map = $this->round_two_download( $to_download );
foreach ( $to_download as $key => $entry ) {
if ( isset( $bytes_map[ $key ]['error'] ) ) {
$results[ $key ] = [ 'error' => $bytes_map[ $key ]['error'] ];
$results[ $key ] = array( 'error' => $bytes_map[ $key ]['error'] );
continue;
}
$results[ $key ] = [
$results[ $key ] = array(
'bytes' => $bytes_map[ $key ]['bytes'],
'mime_type' => 'image/png',
'width' => $entry['width'],
@@ -94,7 +94,7 @@ class PRAutoBlogger_Runware_Image_Batch {
'seed' => $entry['seed'],
'cost_usd' => $this->pricing->estimate_cost( $entry['width'], $entry['height'], $entry['model'] ),
'latency_ms' => (int) ( ( microtime( true ) - $entry['started_at'] ) * 1000 ),
];
);
}
return $results;
@@ -108,10 +108,10 @@ class PRAutoBlogger_Runware_Image_Batch {
* @return array<string, array> Map of key => {error} | {image_url, width, height, model, seed, started_at}.
*/
private function round_one_inference( string $api_key, array $requests ): array {
$headers = [ 'Content-Type: application/json' ];
$headers = array( 'Content-Type: application/json' );
$mh = curl_multi_init();
$handles = [];
$start_times = [];
$handles = array();
$start_times = array();
foreach ( $requests as $key => $req ) {
$model = $this->pricing->resolve_model( (string) ( $req['options']['model'] ?? '' ) );
@@ -123,28 +123,32 @@ class PRAutoBlogger_Runware_Image_Batch {
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, PRAutoBlogger_Runware_Image_Support::API_URL );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, wp_json_encode(
$this->build_payload( $api_key, (string) $req['prompt'], $snap_w, $snap_h, $model, $seed, $steps )
) );
curl_setopt(
$ch,
CURLOPT_POSTFIELDS,
wp_json_encode(
$this->build_payload( $api_key, (string) $req['prompt'], $snap_w, $snap_h, $model, $seed, $steps )
)
);
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_TIMEOUT, PRAUTOBLOGGER_API_TIMEOUT_SECONDS );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
curl_multi_add_handle( $mh, $ch );
$handles[ $key ] = [
$handles[ $key ] = array(
'handle' => $ch,
'model' => $model,
'width' => $snap_w,
'height' => $snap_h,
'seed' => $seed,
];
);
$start_times[ $key ] = microtime( true );
}
$this->run_multi( $mh );
$out = [];
$out = array();
foreach ( $handles as $key => $entry ) {
$out[ $key ] = $this->collect_inference_result( (string) $key, $entry, $start_times[ $key ] );
curl_multi_remove_handle( $mh, $entry['handle'] );
@@ -163,7 +167,7 @@ class PRAutoBlogger_Runware_Image_Batch {
*/
private function round_two_download( array $inferences ): array {
$mh = curl_multi_init();
$handles = [];
$handles = array();
foreach ( $inferences as $key => $entry ) {
$ch = curl_init();
@@ -177,22 +181,22 @@ class PRAutoBlogger_Runware_Image_Batch {
$this->run_multi( $mh );
$out = [];
$out = array();
foreach ( $handles as $key => $ch ) {
$errno = curl_errno( $ch );
if ( 0 !== $errno ) {
$msg = sprintf( 'Runware image download cURL error %d for "%s": %s', $errno, $key, curl_error( $ch ) );
PRAutoBlogger_Logger::instance()->error( $msg, 'runware-image-batch' );
$out[ $key ] = [ 'error' => $msg ];
$out[ $key ] = array( 'error' => $msg );
} else {
$code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
$body = (string) curl_multi_getcontent( $ch );
if ( 200 !== $code || '' === $body ) {
$msg = sprintf( 'Runware image download HTTP %d for "%s" (%d bytes)', $code, $key, strlen( $body ) );
PRAutoBlogger_Logger::instance()->error( $msg, 'runware-image-batch' );
$out[ $key ] = [ 'error' => $msg ];
$out[ $key ] = array( 'error' => $msg );
} else {
$out[ $key ] = [ 'bytes' => $body ];
$out[ $key ] = array( 'bytes' => $body );
}
}
curl_multi_remove_handle( $mh, $ch );
@@ -231,9 +235,12 @@ class PRAutoBlogger_Runware_Image_Batch {
* @return array<int, array<string, mixed>>
*/
private function build_payload( string $api_key, string $prompt, int $width, int $height, string $model, int $seed, int $steps ): array {
return [
[ 'taskType' => 'authentication', 'apiKey' => $api_key ],
[
return array(
array(
'taskType' => 'authentication',
'apiKey' => $api_key,
),
array(
'taskType' => 'imageInference',
'taskUUID' => wp_generate_uuid4(),
'positivePrompt' => $prompt,
@@ -245,8 +252,8 @@ class PRAutoBlogger_Runware_Image_Batch {
'outputFormat' => 'PNG',
'outputType' => 'URL',
'seed' => $seed,
],
];
),
);
}
/**
@@ -263,7 +270,7 @@ class PRAutoBlogger_Runware_Image_Batch {
if ( 0 !== $errno ) {
$msg = sprintf( 'Runware batch inference cURL error %d for "%s": %s', $errno, $key, curl_error( $ch ) );
PRAutoBlogger_Logger::instance()->error( $msg, 'runware-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
$http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
@@ -271,7 +278,7 @@ class PRAutoBlogger_Runware_Image_Batch {
if ( $http_code >= 400 ) {
$msg = sprintf( 'Runware batch inference HTTP %d for "%s": %s', $http_code, $key, substr( $raw, 0, 300 ) );
PRAutoBlogger_Logger::instance()->error( $msg, 'runware-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
try {
@@ -279,16 +286,16 @@ class PRAutoBlogger_Runware_Image_Batch {
} catch ( \Throwable $e ) {
$msg = sprintf( 'Runware batch inference parse error for "%s": %s', $key, $e->getMessage() );
PRAutoBlogger_Logger::instance()->error( $msg, 'runware-image-batch' );
return [ 'error' => $msg ];
return array( 'error' => $msg );
}
return [
return array(
'image_url' => $image_url,
'width' => (int) $entry['width'],
'height' => (int) $entry['height'],
'model' => (string) $entry['model'],
'seed' => (int) $entry['seed'],
'started_at' => $start,
];
);
}
}

View File

@@ -26,12 +26,12 @@ class PRAutoBlogger_Runware_Image_Pricing {
*
* @var array<string, float>
*/
private const COST_PER_IMAGE = [
private const COST_PER_IMAGE = array(
// FLUX.1 schnell — 4-step distilled. Our new default (2026-04-21).
'runware:100@1' => 0.0006,
// FLUX.1 dev — 28-step full model. Higher fidelity, ~30x cost.
'runware:101@1' => 0.02,
];
);
/**
* Default number of inference steps per model. Runware bills per image
@@ -39,10 +39,10 @@ class PRAutoBlogger_Runware_Image_Pricing {
*
* @var array<string, int>
*/
private const DEFAULT_STEPS = [
private const DEFAULT_STEPS = array(
'runware:100@1' => 4,
'runware:101@1' => 28,
];
);
/**
* Resolve the model identifier from a hint, falling back to site option,

View File

@@ -45,7 +45,7 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
* backoff; 4xx (except 429) fail immediately. The image download GET
* is not retried — signed URLs are short-lived.
*/
public function generate_image( string $prompt, int $width, int $height, array $options = [] ): array {
public function generate_image( string $prompt, int $width, int $height, array $options = array() ): array {
$this->assert_valid_dimensions( $width, $height );
$prompt = trim( $prompt );
if ( '' === $prompt ) {
@@ -61,16 +61,19 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
$seed = $this->support->normalize_seed( isset( $options['seed'] ) ? (int) $options['seed'] : null );
$steps = isset( $options['steps'] ) ? (int) $options['steps'] : $this->pricing->default_steps( $model );
$body = $this->build_request_body( $api_key, $prompt, $snap_w, $snap_h, $model, $seed, $steps );
$headers = [ 'Content-Type' => 'application/json' ];
$headers = array( 'Content-Type' => 'application/json' );
$started_at = microtime( true );
$last_error = '';
for ( $attempt = 1; $attempt <= PRAUTOBLOGGER_MAX_RETRIES; $attempt++ ) {
$response = wp_remote_post( PRAutoBlogger_Runware_Image_Support::API_URL, [
'timeout' => PRAUTOBLOGGER_API_TIMEOUT_SECONDS,
'headers' => $headers,
'body' => wp_json_encode( $body ),
] );
$response = wp_remote_post(
PRAutoBlogger_Runware_Image_Support::API_URL,
array(
'timeout' => PRAUTOBLOGGER_API_TIMEOUT_SECONDS,
'headers' => $headers,
'body' => wp_json_encode( $body ),
)
);
if ( is_wp_error( $response ) ) {
$last_error = $response->get_error_message();
@@ -109,7 +112,7 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
$image_url = $this->support->extract_image_url( $raw );
$image_bytes = $this->support->download_image_bytes( $image_url );
return [
return array(
'bytes' => $image_bytes,
'mime_type' => 'image/png',
'width' => $snap_w,
@@ -118,7 +121,7 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
'seed' => $seed,
'cost_usd' => $this->pricing->estimate_cost( $snap_w, $snap_h, $model ),
'latency_ms' => (int) ( ( microtime( true ) - $started_at ) * 1000 ),
];
);
}
throw new \RuntimeException(
@@ -160,7 +163,7 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
}
/** {@inheritDoc} */
public function estimate_cost( int $width, int $height, array $options = [] ): float {
public function estimate_cost( int $width, int $height, array $options = array() ): float {
$model = $this->pricing->resolve_model( (string) ( $options['model'] ?? '' ) );
return $this->pricing->estimate_cost( $width, $height, $model );
}
@@ -181,50 +184,62 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
try {
$api_key = $this->support->get_api_key();
} catch ( \RuntimeException $e ) {
return [ 'status' => 'error', 'message' => $e->getMessage() ];
return array(
'status' => 'error',
'message' => $e->getMessage(),
);
}
$body = [
[ 'taskType' => 'authentication', 'apiKey' => $api_key ],
];
$body = array(
array(
'taskType' => 'authentication',
'apiKey' => $api_key,
),
);
$response = wp_remote_post( PRAutoBlogger_Runware_Image_Support::API_URL, [
'timeout' => 15,
'headers' => [ 'Content-Type' => 'application/json' ],
'body' => wp_json_encode( $body ),
] );
$response = wp_remote_post(
PRAutoBlogger_Runware_Image_Support::API_URL,
array(
'timeout' => 15,
'headers' => array( 'Content-Type' => 'application/json' ),
'body' => wp_json_encode( $body ),
)
);
if ( is_wp_error( $response ) ) {
return [
return array(
'status' => 'error',
'message' => __( 'Could not reach Runware API.', 'prautoblogger' ),
'debug' => $response->get_error_message(),
];
);
}
$status = (int) wp_remote_retrieve_response_code( $response );
$raw = (string) wp_remote_retrieve_body( $response );
if ( 200 !== $status ) {
return [
return array(
'status' => 'error',
'message' => sprintf( __( 'Runware returned HTTP %d.', 'prautoblogger' ), $status ),
'debug' => substr( $raw, 0, 200 ),
];
);
}
$decoded = json_decode( $raw, true );
if ( is_array( $decoded ) && isset( $decoded['errors'] ) && ! empty( $decoded['errors'] ) ) {
$first = $decoded['errors'][0] ?? [];
$first = $decoded['errors'][0] ?? array();
$msg = is_array( $first ) ? (string) ( $first['message'] ?? '' ) : (string) $first;
return [
return array(
'status' => 'error',
'message' => __( 'Runware rejected the API key.', 'prautoblogger' ),
'debug' => substr( $msg, 0, 200 ),
];
);
}
return [ 'status' => 'ok', 'message' => __( 'Runware API key valid.', 'prautoblogger' ) ];
return array(
'status' => 'ok',
'message' => __( 'Runware API key valid.', 'prautoblogger' ),
);
}
/**
@@ -250,12 +265,12 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
int $seed,
int $steps
): array {
return [
[
return array(
array(
'taskType' => 'authentication',
'apiKey' => $api_key,
],
[
),
array(
'taskType' => 'imageInference',
'taskUUID' => wp_generate_uuid4(),
'positivePrompt' => $prompt,
@@ -267,8 +282,8 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
'outputFormat' => 'PNG',
'outputType' => 'URL',
'seed' => $seed,
],
];
),
);
}
/**
@@ -286,7 +301,10 @@ class PRAutoBlogger_Runware_Image_Provider implements PRAutoBlogger_Image_Provid
throw new \InvalidArgumentException(
sprintf(
esc_html__( 'Image dimensions %1$dx%2$d outside supported range (%3$d–%4$d px).', 'prautoblogger' ),
$width, $height, self::MIN_DIMENSION_PX, self::MAX_DIMENSION_PX
$width,
$height,
self::MIN_DIMENSION_PX,
self::MAX_DIMENSION_PX
)
);
}

View File

@@ -68,7 +68,7 @@ class PRAutoBlogger_Runware_Image_Support {
// Runware wraps errors in an `errors` array.
if ( isset( $decoded['errors'] ) && is_array( $decoded['errors'] ) && ! empty( $decoded['errors'] ) ) {
$first = $decoded['errors'][0] ?? [];
$first = $decoded['errors'][0] ?? array();
$msg = is_array( $first )
? (string) ( $first['message'] ?? wp_json_encode( $first ) )
: (string) $first;
@@ -80,7 +80,7 @@ class PRAutoBlogger_Runware_Image_Support {
);
}
$data = $decoded['data'] ?? [];
$data = $decoded['data'] ?? array();
if ( ! is_array( $data ) || empty( $data ) ) {
throw new \RuntimeException(
esc_html__( 'Runware response contained no data.', 'prautoblogger' )
@@ -115,9 +115,12 @@ class PRAutoBlogger_Runware_Image_Support {
* @throws \RuntimeException On HTTP error or empty body.
*/
public function download_image_bytes( string $image_url ): string {
$response = wp_remote_get( $image_url, [
'timeout' => 30,
] );
$response = wp_remote_get(
$image_url,
array(
'timeout' => 30,
)
);
if ( is_wp_error( $response ) ) {
throw new \RuntimeException(

View File

@@ -61,7 +61,7 @@ interface PRAutoBlogger_Image_Provider_Interface {
* an invalid response shape.
* @throws \InvalidArgumentException If dimensions are out of range.
*/
public function generate_image( string $prompt, int $width, int $height, array $options = [] ): array;
public function generate_image( string $prompt, int $width, int $height, array $options = array() ): array;
/**
* Estimate the USD cost of a single generation call before making it.
@@ -75,7 +75,7 @@ interface PRAutoBlogger_Image_Provider_Interface {
*
* @return float Estimated cost in USD for a single image at the given dimensions.
*/
public function estimate_cost( int $width, int $height, array $options = [] ): float;
public function estimate_cost( int $width, int $height, array $options = array() ): float;
/**
* Machine-readable provider identifier used in logs and settings.

View File

@@ -35,7 +35,7 @@ interface PRAutoBlogger_LLM_Provider_Interface {
*
* @throws \RuntimeException On API error after retries exhausted.
*/
public function send_chat_completion( array $messages, string $model, array $options = [] ): array;
public function send_chat_completion( array $messages, string $model, array $options = array() ): array;
/**
* Get the list of available models from the provider.