app/classes/ReleaseInsights/Json.php (72 lines of code) (raw):

<?php declare(strict_types=1); namespace ReleaseInsights; use Cache\Cache; class Json { /** * @param array<string, string> $data */ public function __construct( public array $data = [], public mixed $jsonp = false, public bool $pretty_print = false, ) { } /** * Return a JSON/JSONP representation of data with the right HTTP headers */ public function output(): string { $json = $this->pretty_print ? json_encode($this->data, JSON_PRETTY_PRINT) : json_encode($this->data); $mime = 'application/json'; if (is_string($this->jsonp)) { $mime = 'application/javascript'; $json = $this->jsonp . '(' . $json . ')'; } ob_start(); header("access-control-allow-origin: *"); // * is OK as our Json API is public and readonly header("Content-type: {$mime}; charset=UTF-8"); header("Content-Length: " . strlen($json)); echo $json; $json = ob_get_contents(); ob_end_clean(); return $json; } /** * Return HTTP code 400 and an error message if an API call is incorrect */ public function outputError(): string { $this->pretty_print = true; http_response_code(400); return $this->output(); } /** * Output Json data */ public function render(): void { if (array_key_exists('error', $this->data)) { echo $this->outputError(); } else { $this->jsonp = $_GET['callback'] ?? false; echo $this->output(); } } // Below are static methods imported from the Utils class, refactoring in progress /** * @return array<mixed> $template_data */ public static function load(string $url, int $ttl = 0): array { if (! $data = Cache::getKey($url, $ttl)) { $data = Utils::getFile($url); // Error fetching external data, don't cache. Safety net // @codeCoverageIgnoreStart if ($data === false) { return ['error' => 'URL triggered an error']; } // @codeCoverageIgnoreEnd // No data returned, bug or incorrect data, don't cache. if (empty($data)) { return ['error' => 'URL provided no data']; } // Invalid Json, don't cache. if (! json_validate($data)) { return ['error' => 'Invalid JSON source']; } Cache::setKey($url, $data, $ttl); } return self::toArray($data); } /** * Return an Array from a Json string * This is an utility function as we use json_decode in multiple places, * always with the same options. That will make these calls shorter, * with a more explicit function name and will allow to change default * values at the app level. * * @return array<mixed> Associative array from a Json string */ public static function toArray(string $data): array { $data = json_decode( json: $data, associative: true, depth: 512, ); return is_null($data) ? [] : $data; } }