>, error:?string} */ public function posts(string $baseUrl): array { $api = $this->apiBase($baseUrl); if ($api === null) { return ['posts' => [], 'error' => 'No usable URL.']; } $posts = []; for ($page = 1; $page <= self::MAX_PAGES; $page++) { $url = $api . '/posts?per_page=' . self::PER_PAGE . '&page=' . $page . '&_embed=wp:featuredmedia,wp:term'; $batch = $this->get($url); if ($batch === null) { // Page 1 failing is a real error; later pages simply mean the end // (WordPress answers 400 rest_post_invalid_page_number past it). return $page === 1 ? ['posts' => [], 'error' => 'The source did not answer with a post list. Check the URL.'] : ['posts' => $posts, 'error' => null]; } $posts = array_merge($posts, $batch); if (count($batch) < self::PER_PAGE) { break; } } return ['posts' => $posts, 'error' => null]; } /** * Category id => name, for showing what a post was filed under over there. * * @return array */ public function categories(string $baseUrl): array { $api = $this->apiBase($baseUrl); if ($api === null) { return []; } $rows = $this->get($api . '/categories?per_page=' . self::PER_PAGE) ?? []; $map = []; foreach ($rows as $row) { $map[(int)($row['id'] ?? 0)] = html_entity_decode((string)($row['name'] ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8'); } return $map; } /** * Turns whatever the editor typed into the v2 API base. * "vitec.com/blog", "https://vitec.com/blog/" and a full ".../wp-json/wp/v2" * all end up the same. */ public function apiBase(string $baseUrl): ?string { $baseUrl = trim($baseUrl); if ($baseUrl === '') { return null; } if (!preg_match('#^https?://#i', $baseUrl)) { $baseUrl = 'https://' . $baseUrl; } $baseUrl = rtrim($baseUrl, '/'); if (str_contains($baseUrl, '/wp-json')) { return $baseUrl; } return $baseUrl . '/wp-json/wp/v2'; } /** @return array>|null */ private function get(string $url): ?array { try { $response = GeneralUtility::makeInstance(RequestFactory::class) ->request($url, 'GET', ['timeout' => self::TIMEOUT, 'headers' => ['Accept' => 'application/json']]); if ($response->getStatusCode() !== 200) { return null; } $decoded = json_decode((string)$response->getBody(), true); return is_array($decoded) ? $decoded : null; } catch (\Throwable $e) { return null; } } }