feat: add names and nameByID endpoints #37

Merged
Ghost merged 5 commits from feat/35-and-36 into development 2022-04-20 09:28:19 -04:00
3 changed files with 122 additions and 67 deletions
Showing only changes of commit 6b4a13da72 - Show all commits

View File

@ -3,56 +3,44 @@
namespace App\Data; namespace App\Data;
use App\Exceptions\ItemNotFoundException; use App\Exceptions\ItemNotFoundException;
use Exception;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Config\GiteaConfig; use App\Config\GiteaConfig;
use Illuminate\Support\Facades\Log;
class ItemsCollection class ItemsCollection
{ {
protected array $items; protected Collection $items;
protected array $locales; protected Collection $locales;
private string $items_file_key = 'items.json'; private string $items_cache_key = 'items';
private string $locales_file_key = 'locales.json'; private string $locales_cache_key = 'locales';
/**
* @throws Exception
*/
public function __construct() public function __construct()
{ {
if (!File::exists(storage_path($this->items_file_key))) { if (!Cache::has($this->items_cache_key)) {
$this->refreshItemsCache(); $this->refreshItemsCache();
} else { } else {
$content = file_get_contents(storage_path($this->items_file_key)); $this->items = Cache::get($this->items_cache_key);
$this->items = json_decode($content, true);
} }
if (!File::exists(storage_path($this->locales_file_key ))) { if (!Cache::has($this->locales_cache_key)) {
$this->refreshLocalesCache(); $this->refreshLocalesCache();
} else { } else {
$content = file_get_contents(storage_path($this->locales_file_key )); $this->locales = Cache::get($this->locales_cache_key);
$this->locales = json_decode($content, true);
} }
} }
/**
* @return void
* @throws Exception
*/
public function refreshLocalesCache(): void public function refreshLocalesCache(): void
{ {
$time_limit = ini_get('max_execution_time'); $this->locales = collect();
$memory_limit = ini_get('memory_limit');
set_time_limit(180);
ini_set('memory_limit', '256M');
$this->locales = [];
$rawLocalesGlobalBaseUrl = GiteaConfig::RAW_LOCALES_GLOBAL_BASE_URL; $rawLocalesGlobalBaseUrl = GiteaConfig::RAW_LOCALES_GLOBAL_BASE_URL;
// Getting all locales in project/assets/database/locales/global from the Server development branch repository // Getting all locales in project/assets/database/locales/global from the Server development branch repository
$localesList = Http::withOptions(['verify' => false])->get(GiteaConfig::LOCALES_GLOBAL_URL)->json();
$localesList = collect(Http::withOptions(['verify' => false])->get(GiteaConfig::LOCALES_GLOBAL_URL)->json());
foreach ($localesList as $item) { foreach ($localesList as $item) {
// Extract the json name for the locale // Extract the json name for the locale
preg_match('/([a-z]{2}(-[a-z]{2})?).json/', $item['name'], $currentLocaleName, PREG_OFFSET_CAPTURE); preg_match('/([a-z]{2}(-[a-z]{2})?).json/', $item['name'], $currentLocaleName, PREG_OFFSET_CAPTURE);
@ -62,53 +50,35 @@ class ItemsCollection
$trimmedCurrentLocaleName = trim($currentLocaleName[1][0]); $trimmedCurrentLocaleName = trim($currentLocaleName[1][0]);
$currentLocaleJson = Http::withOptions(['verify' => false]) $currentLocaleJson = Http::withOptions(['verify' => false])
->get("$rawLocalesGlobalBaseUrl/$trimmedCurrentLocaleName.json")->json(); ->get("${rawLocalesGlobalBaseUrl}/${trimmedCurrentLocaleName}.json")->json();
$templateLocale = $currentLocaleJson['templates']; $templateLocale = collect($currentLocaleJson['templates']);
$customizationLocale = $currentLocaleJson['customization']; $customizationLocale = collect($currentLocaleJson['customization']);
$this->locales[$trimmedCurrentLocaleName] = array_merge($templateLocale, $customizationLocale); $this->locales = $this->locales->merge([$trimmedCurrentLocaleName => $templateLocale->concat($customizationLocale)]);
} }
if (!$handle = fopen(storage_path($this->locales_file_key ), 'w')) { Cache::put($this->locales_cache_key, $this->locales);
throw new Exception('Cannot open the file');
}
fwrite($handle, json_encode($this->locales));
fclose($handle);
set_time_limit($time_limit);
ini_set('memory_limit', $memory_limit);
} }
/** /**
* @return void * @return void
* @throws Exception
*/ */
public function refreshItemsCache(): void public function refreshItemsCache(): void
{ {
$time_limit = ini_get('max_execution_time'); $this->items = collect(Http::withOptions(['verify' => false])->get(GiteaConfig::RAW_ITEMS_URL)->json());
$memory_limit = ini_get('memory_limit'); $this->items = $this->items->merge(collect(Http::withOptions(['verify' => false])
set_time_limit(180); ->get(GiteaConfig::RAW_CUSTOMIZATION_URL)->json()));
ini_set('memory_limit', '256M'); Cache::put($this->items_cache_key, $this->items);
$items = Http::withOptions(['verify' => false])->get(GiteaConfig::RAW_ITEMS_URL)->json();
$customization = Http::withOptions(['verify' => false])->get(GiteaConfig::RAW_CUSTOMIZATION_URL)->json();
$this->items = array_merge($items, $customization);
if (!$handle = fopen(storage_path($this->items_file_key ), 'w')) {
throw new Exception('Cannot open the file');
}
fwrite($handle, json_encode($this->items));
fclose($handle);
set_time_limit($time_limit);
ini_set('memory_limit', $memory_limit);
} }
/** /**
* @return array * @return Collection
*/ */
public function getLocales(): array public function getLocales(): Collection
{ {
return array_keys($this->locales); return $this->locales->keys();
} }
/** /**
* @return void * @return void
* @throws Exception
*/ */
public function refreshAllCache(): void public function refreshAllCache(): void
{ {
@ -137,8 +107,7 @@ class ItemsCollection
*/ */
public function findItem(string $query, string $locale): Collection public function findItem(string $query, string $locale): Collection
{ {
$items = collect($this->items); return $this->items->filter(function ($val, $key) use ($query, $locale) {
return $items->filter(function ($val, $key) use ($query, $locale) {
return $this->contains($val['_id'], $query) return $this->contains($val['_id'], $query)
|| $this->contains($val['_name'], $query) || $this->contains($val['_name'], $query)
|| $this->contains($val['_parent'], $query) || $this->contains($val['_parent'], $query)
@ -171,14 +140,13 @@ class ItemsCollection
]; ];
} }
public function getHierarchy(string $id, string $locale = 'en'): Collection public function getHierarchy(string $id, string $locale = 'en'): Collection {
{
// Return 404 if the item does not exist // Return 404 if the item does not exist
$itemData = $this->items[$id] ?? throw new ItemNotFoundException('Item not found'); $itemData = $this->items[$id] ?? throw new ItemNotFoundException('Item not found');
// Initialize the hierarchy with the current item // Initialize the hierarchy with the current item
$item = [ $item = [
'item' => [ 'item'=> [
'_id' => $itemData['_id'], '_id' => $itemData['_id'],
'_name' => $itemData['_name'], '_name' => $itemData['_name'],
'_parent' => $itemData['_parent'] '_parent' => $itemData['_parent']
@ -192,7 +160,7 @@ class ItemsCollection
$itemtId = $item['item']['_parent']; $itemtId = $item['item']['_parent'];
$itemData = $this->items[$itemtId] ?? null; $itemData = $this->items[$itemtId] ?? null;
$item = [ $item = [
'item' => [ 'item'=> [
'_id' => $itemData['_id'], '_id' => $itemData['_id'],
'_name' => $itemData['_name'], '_name' => $itemData['_name'],
'_parent' => $itemData['_parent'] '_parent' => $itemData['_parent']
@ -204,4 +172,46 @@ class ItemsCollection
return $hierarchy; return $hierarchy;
} }
public function getItemLocale(string $locale, string $itemID): array {
return $this->locales[$locale][$itemID] ?? [];
}
/**
* @param string $locale the chosen local. Default to 'en'
* @return array
* @throws ItemNotFoundException
*/
public function getAllItemsName(string $locale): Collection
{
return $this->items->map(function ($item) use ($locale) {
return [
'item' => [
'_id' => $item['_id'],
],
'locale' => collect($this->getItemLocale($locale, $item['_id']))->only(['Name', 'ShortName'])
];
})->filter(function ($item) {
return json_encode($item['locale']) != '[]';
})->values();
}
/**
* @param string $id the item ID to look for
* @param string $locale the chosen local. Default to 'en'
* @return array
* @throws ItemNotFoundException
*/
public function getItemNameById(string $id, string $locale): array
{
$itemLocale = $this->locales[$locale][$id] ?? '';
if ($itemLocale == '') {
return $itemLocale;
}
return [
'locale' => collect($itemLocale)->only(['Name', 'ShortName'])
];
}
} }

View File

@ -61,6 +61,49 @@ class ItemController extends Controller
} }
// $router->get('item/list', 'ItemController@getAllItems');
// $router->get('item/nameByID', 'ItemController@getItemNameByID');
/**
* @param Request $request
* @return JsonResponse
*/
public function getAllItemsName(Request $request): JsonResponse
{
try {
return response()->json(
$this->itemsCollection->getAllItemsName($request->query('locale', 'en'))
);
} catch (Throwable $exception) {
Log::error($exception->getMessage());
Log::error($exception->getTraceAsString());
return response()->json([
'error' => 'Error during items collection.',
], Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* @param Request $request
* @return JsonResponse
*/
public function getItemNameByID(Request $request): JsonResponse
{
try {
return response()->json(
$this->itemsCollection->getItemNameById(
$request->query('id', ''), $request->query('locale', 'en')
)
);
} catch (Throwable $exception) {
Log::error($exception->getMessage());
Log::error($exception->getTraceAsString());
return response()->json([
'error' => 'Item not found.',
], Response::HTTP_NOT_FOUND);
}
}
/** /**
* @param Request $request The request * @param Request $request The request
* @return JsonResponse Either {"error":"item not found"} or an object containing * @return JsonResponse Either {"error":"item not found"} or an object containing

View File

@ -26,6 +26,8 @@ $router->group(['prefix' => 'api'], function () use ($router) {
$router->get('refresh', 'ItemController@refreshAllCache'); $router->get('refresh', 'ItemController@refreshAllCache');
$router->post('search', 'ItemController@search'); $router->post('search', 'ItemController@search');
$router->get('item/hierarchy', 'ItemController@getHierarchy'); $router->get('item/hierarchy', 'ItemController@getHierarchy');
$router->get('item/names', 'ItemController@getAllItemsName');
$router->get('item/nameByID', 'ItemController@getItemNameByID');
$router->get('item', 'ItemController@getItem'); $router->get('item', 'ItemController@getItem');
}); });