// === WordPress プロバイダ実装 === // クラスの外に置く(plugins_loaded 後でもOK) add_filter('hato_post_provider', function($result, $provider, $a, $payload){ if ($provider !== 'wordpress') return $result; // 資格情報 $username = trim((string)($a['hatena_id'] ?? '')); // UI上は Hatena ID フィールドを WPユーザー名として流用 $site_url = trim((string)($a['blog_id'] ?? '')); // UI上は Blog ID フィールドを サイトURLとして流用 $app_pass = trim((string)($a['api_key'] ?? '')); // UI上は APIキー フィールドを Application Password として流用 $is_draft = !empty($a['draft']); if ($username === '' || $site_url === '' || $app_pass === '' || !preg_match('#^https?://#',$site_url)) { return ['code'=>400, 'note'=>'missing wordpress credentials (username/site_url/app_password)']; } // REST エンドポイント $endpoint = rtrim($site_url, '/').'/wp-json/wp/v2/posts'; // ボディ $title = (string)($payload['title'] ?? ''); $content = (string)($payload['content_html'] ?? ''); $status = $is_draft ? 'draft' : 'publish'; // (任意)タグを投げたい場合は slug/ID 解決が必要。ここでは本文・タイトル・公開状態のみ。 $body = [ 'title' => $title, 'content' => $content, 'status' => $status, ]; // Basic 認証(ユーザー名:アプリパス) $headers = [ 'Authorization' => 'Basic '. base64_encode($username.':'.$app_pass), 'Content-Type' => 'application/json; charset=utf-8', ]; // 投げる $resp = wp_remote_post($endpoint, [ 'headers' => $headers, 'body' => wp_json_encode($body), 'timeout' => 20, ]); if (is_wp_error($resp)) { return ['code'=>0, 'note'=>$resp->get_error_message()]; } $code = (int) wp_remote_retrieve_response_code($resp); $raw = (string) wp_remote_retrieve_body($resp); $json = json_decode($raw, true); // 成功時は 201 Created。URL は 'link' or 'guid' から拾う if ($code >= 200 && $code < 300) { $url = ''; if (is_array($json)) { $url = (string)($json['link'] ?? ($json['guid']['rendered'] ?? '')); } return ['code'=>$code, 'url'=>$url, 'note'=>'ok']; } else { // エラーメッセージを返す $msg = ''; if (is_array($json) && !empty($json['message'])) $msg = (string)$json['message']; if ($msg === '') $msg = mb_strimwidth($raw, 0, 400, '…'); return ['code'=>$code, 'note'=>$msg]; } }, 10, 4);