Skip to content

Commit

Permalink
Remove dependency to external mozillal10n/Json
Browse files Browse the repository at this point in the history
- mozillal10n/json no longer needed in composer
- Move all json related functions in Utils to a new Json class
- Update tests
  • Loading branch information
pascalchevrel committed May 6, 2024
1 parent c3afdd3 commit 045c39b
Show file tree
Hide file tree
Showing 25 changed files with 230 additions and 156 deletions.
4 changes: 1 addition & 3 deletions app/classes/ReleaseInsights/Bugzilla.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace ReleaseInsights;

use ReleaseInsights\URL;

class Bugzilla
{
/**
Expand Down Expand Up @@ -51,7 +49,7 @@ public static function linkify(string $text): ?string
*/
public static function getBugsFromHgWeb(string $query, bool $detect_backouts = false, int $cache_ttl = 0): array
{
$results = Utils::getJson($query, $cache_ttl)['pushes'] ?? null;
$results = Json::load($query, $cache_ttl)['pushes'] ?? null;

// Handle the lack of data from HG
if (empty($results)) {
Expand Down
14 changes: 6 additions & 8 deletions app/classes/ReleaseInsights/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace ReleaseInsights;

use ReleaseInsights\URL;

class Data
{
/** @var array<string, string> $future_releases */
Expand Down Expand Up @@ -42,7 +40,7 @@ public function getFutureReleases(): array
public function getESRReleases(): array
{
// Historical data from Product Details, cache a week
$esr_releases = Utils::getJson($this->pd_url . 'firefox.json', $this->cache_duration)['releases'];
$esr_releases = Json::load($this->pd_url . 'firefox.json', $this->cache_duration)['releases'];

// Reduce to only ESR releases
$esr_releases = array_filter(
Expand Down Expand Up @@ -81,8 +79,8 @@ public function getLatestMajorRelease(): array
public function getPastReleases(bool $dot_releases = true): array
{
// Historical data from Product Details, cache a week
$major_releases = Utils::getJson($this->pd_url . 'firefox_history_major_releases.json', $this->cache_duration);
$minor_releases = $dot_releases == true ? Utils::getJson($this->pd_url . 'firefox_history_stability_releases.json', $this->cache_duration) : [];
$major_releases = Json::load($this->pd_url . 'firefox_history_major_releases.json', $this->cache_duration);
$minor_releases = $dot_releases == true ? Json::load($this->pd_url . 'firefox_history_stability_releases.json', $this->cache_duration) : [];
$all_releases = [...$major_releases, ...$minor_releases];

// Sort releases by release date
Expand Down Expand Up @@ -119,7 +117,7 @@ public function getPastReleases(bool $dot_releases = true): array
*/
public function getPastBetas(): array
{
return Utils::getJson($this->pd_url . 'firefox_history_development_releases.json', $this->cache_duration);
return Json::load($this->pd_url . 'firefox_history_development_releases.json', $this->cache_duration);
}

/**
Expand All @@ -129,7 +127,7 @@ public function getPastBetas(): array
*/
public function getMajorPastReleases(): array
{
return Utils::getJson($this->pd_url . 'firefox_history_major_releases.json', $this->cache_duration);
return Json::load($this->pd_url . 'firefox_history_major_releases.json', $this->cache_duration);
}

/**
Expand All @@ -149,7 +147,7 @@ public function getMajorReleases(): array
public function getFirefoxVersions(): array
{
// Cache Product Details versions, 15mn cache
return Utils::getJson($this->pd_url . 'firefox_versions.json', $this->cache_duration);
return Json::load($this->pd_url . 'firefox_versions.json', $this->cache_duration);
}

/**
Expand Down
2 changes: 0 additions & 2 deletions app/classes/ReleaseInsights/ESR.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace ReleaseInsights;

use ReleaseInsights\Version;

class ESR
{
/**
Expand Down
123 changes: 123 additions & 0 deletions app/classes/ReleaseInsights/Json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?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: *");
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)) {
print_r($this->outputError());
} else {
$this->jsonp = $_GET['callback'] ?? false;
print_r($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);

// No data returned, bug or incorrect date, don't cache.
if (empty($data)) {
return [];
}

// Invalid Json, don't cache.
if (! self::isValid($data)) {
return [];
}

Cache::setKey($url, $data, $ttl);
}

return self::toArray($data);
}

public static function isValid(string $data): bool
{
return is_string($data)
&& is_array(json_decode($data, true))
&& (json_last_error() == JSON_ERROR_NONE);
}

/**
* 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;
}
}

6 changes: 2 additions & 4 deletions app/classes/ReleaseInsights/Nightly.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace ReleaseInsights;

Use ReleaseInsights\URL;

class Nightly
{
public string $version;
Expand All @@ -17,7 +15,7 @@ public function __construct(
public string $AUS = URL::Balrog->value,
public string $update_status = 'emergency_shutoff/Firefox/nightly',
) {
$this->version = Utils::getJson(
$this->version = Json::load(
$this->pd . 'firefox_versions.json',
604800
)['FIREFOX_NIGHTLY'];
Expand All @@ -39,7 +37,7 @@ public function __construct(
}

if ($this->auto_updates === false) {
$tmp = Utils::getJson($this->AUS . $this->update_status, 1);
$tmp = Json::load($this->AUS . $this->update_status, 1);
$tmp = $tmp['comment'] ?? '';
$this->emergency_message = Utils::secureText($tmp);
unset($tmp);
Expand Down
2 changes: 0 additions & 2 deletions app/classes/ReleaseInsights/Release.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
namespace ReleaseInsights;

use DateTime;
use ReleaseInsights\ReleaseStatus as Status;
use ReleaseInsights\URL;

class Release
{
Expand Down
76 changes: 3 additions & 73 deletions app/classes/ReleaseInsights/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use Cache\Cache;
use DateTime;
use GuzzleHttp\Client;
use Json\Json;
use ReleaseInsights\URL;

class Utils
{
Expand Down Expand Up @@ -44,7 +42,7 @@ public static function getCrashesForBuildID(int $buildid): array
Cache::setKey($cache_id, $data);
}

return self::arrayFromJson($data);
return Json::toArray($data);
}

/**
Expand Down Expand Up @@ -78,27 +76,7 @@ public static function getBugsforCrashSignature(string $signature): array
Cache::setKey($cache_id, $data);
}

return self::arrayFromJson($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 arrayFromJson(string $data): array
{
$data = json_decode(
json: $data,
associative: true,
depth: 512,
);

return is_null($data) ? [] : $data;
return Json::toArray($data);
}

/**
Expand Down Expand Up @@ -192,7 +170,7 @@ public static function secureText(string $string): string
}

/**
* getFile code coverage is done through its consumer getJson
* getFile code coverage is done through its main consumer Json::load()
*/
public static function getFile(string $url): string
{
Expand Down Expand Up @@ -228,37 +206,6 @@ public static function getFile(string $url): string
// @codeCoverageIgnoreEnd
}

/**
* @return array<mixed> $template_data
*/
public static function getJson(string $url, int $ttl = 0): array
{
if (! $data = Cache::getKey($url, $ttl)) {
$data = Utils::getFile($url);

// No data returned, bug or incorrect date, don't cache.
if (empty($data)) {
return [];
}

// Invalid Json, don't cache.
if (! self::isJson($data)) {
return [];
}

Cache::setKey($url, $data, $ttl);
}

return self::arrayFromJson($data);
}

public static function isJson(string $data): bool
{
return is_string($data)
&& is_array(json_decode($data, true))
&& (json_last_error() == JSON_ERROR_NONE);
}

public static function mtrim(string $string): string
{
$string = explode(' ', $string);
Expand Down Expand Up @@ -351,21 +298,4 @@ public static function isDateBetweenDates(DateTime $date, DateTime $startDate, D
{
return $date > $startDate && $date < $endDate;
}

/**
* Utility function to output Json data
*
* @param array<mixed> $data
*/
public static function renderJson(array $data): void
{
// Output a JSON or JSONP representation of search results
$json = new Json();

if (array_key_exists('error', $data)) {
print_r($json->outputError($data['error']));
} else {
print_r($json->outputContent($data, $_GET['callback'] ?? false));
}
}
}
4 changes: 3 additions & 1 deletion app/controllers/api/esr_releases.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use ReleaseInsights\Json;

$json = include MODELS . 'api/esr_releases.php';

ReleaseInsights\Utils::renderJson($json);
(new Json($json))->render();
4 changes: 3 additions & 1 deletion app/controllers/api/external.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use ReleaseInsights\Json;

$json = include MODELS . 'api/external.php';

ReleaseInsights\Utils::renderJson($json);
(new Json($json))->render();
4 changes: 3 additions & 1 deletion app/controllers/api/firefox_releases.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

declare(strict_types=1);

use ReleaseInsights\Json;

$json = include MODELS . 'api/firefox_releases.php';

ReleaseInsights\Utils::renderJson($json);
(new Json($json))->render();
Loading

0 comments on commit 045c39b

Please sign in to comment.