| 1 |
<?php |
| 2 |
|
| 3 |
namespace Templately\API; |
| 4 |
|
| 5 |
class AiCredit extends API { |
| 6 |
|
| 7 |
/** |
| 8 |
* AI Studio — credit balance and usage history. |
| 9 |
* |
| 10 |
* Both upstream operations already accept `api_key` via the backend's |
| 11 |
* `Helper::tokenOrApi()`, so unlike the workspace/subscription operations |
| 12 |
* these needed no schema change to be callable from the plugin. |
| 13 |
* |
| 14 |
* Note this is the GraphQL surface, not the `v2/ai/available-credits` REST |
| 15 |
* endpoint that `LogoGeneration` uses — that one returns only a single |
| 16 |
* `available_credit` integer, while AI Studio needs the full stats payload |
| 17 |
* (subscription vs purchased split, totals, plan interval). |
| 18 |
*/ |
| 19 |
public function register_routes() { |
| 20 |
$this->get( 'ai-credit/stats', [ $this, 'get_stats' ] ); |
| 21 |
$this->get( 'ai-credit/history', [ $this, 'get_history' ] ); |
| 22 |
} |
| 23 |
|
| 24 |
/** |
| 25 |
* Credit balance. |
| 26 |
* |
| 27 |
* `stats` comes back as a JSON *string* which the client parses — same |
| 28 |
* contract the web dashboard's `available-credit.tsx` works against. It is |
| 29 |
* decoded here so the React side gets a real object and does not have to |
| 30 |
* repeat the parse-and-guard dance. |
| 31 |
*/ |
| 32 |
public function get_stats() { |
| 33 |
$response = $this->http()->query( 'getAvailableCredit', 'stats', [ |
| 34 |
'api_key' => $this->api_key, |
| 35 |
] )->post(); |
| 36 |
|
| 37 |
if ( is_wp_error( $response ) ) { |
| 38 |
return $this->error( 'invalid_ai_credit_stats_response', $response->get_error_message(), 'ai-credit/stats', 400 ); |
| 39 |
} |
| 40 |
|
| 41 |
$stats = []; |
| 42 |
|
| 43 |
if ( ! empty( $response['stats'] ) ) { |
| 44 |
$decoded = json_decode( $response['stats'], true ); |
| 45 |
|
| 46 |
if ( is_array( $decoded ) ) { |
| 47 |
$stats = $decoded; |
| 48 |
} |
| 49 |
} |
| 50 |
|
| 51 |
return $this->success( [ 'stats' => $stats ] ); |
| 52 |
} |
| 53 |
|
| 54 |
/** |
| 55 |
* Paginated credit usage history. |
| 56 |
*/ |
| 57 |
public function get_history() { |
| 58 |
$page = $this->get_param( 'page', 1, 'intval' ); |
| 59 |
// Clamped: `per_page` reaches the upstream API verbatim, and an unbounded |
| 60 |
// value lets any caller ask it for the whole table in one request. |
| 61 |
$per_page = max( 1, min( 100, $this->get_param( 'per_page', 10, 'intval' ) ) ); |
| 62 |
$page = max( 1, $page ); |
| 63 |
|
| 64 |
$response = $this->http()->mutation( |
| 65 |
'getAiCreditUseHistory', |
| 66 |
'current_page, total_page, data{ id, template_name, template_type, credit_cost, created_at }', |
| 67 |
[ |
| 68 |
'api_key' => $this->api_key, |
| 69 |
'page' => $page, |
| 70 |
'per_page' => $per_page, |
| 71 |
] |
| 72 |
)->post(); |
| 73 |
|
| 74 |
if ( is_wp_error( $response ) ) { |
| 75 |
return $this->error( 'invalid_ai_credit_history_response', $response->get_error_message(), 'ai-credit/history', 400 ); |
| 76 |
} |
| 77 |
|
| 78 |
return $this->success( $response ); |
| 79 |
} |
| 80 |
} |
| 81 |
|