feat: add item and locales caching based on Gitea

This commit is contained in:
Mangiang 2021-10-11 17:29:15 -04:00
parent b68eac70f9
commit 6db043ce6b
4 changed files with 88 additions and 27 deletions

View File

@ -0,0 +1,9 @@
<?php
namespace App\Config;
final class GiteaConfig {
public const RAW_ITEMS_URL = 'https://dev.sp-tarkov.com/SPT-AKI/Server/raw/branch/development/project/assets/database/templates/items.json';
public const LOCALES_GLOBAL_URL = 'https://dev.sp-tarkov.com/api/v1/repos/SPT-AKI/Server/contents/project%2Fassets%2Fdatabase%2Flocales%2Fglobal';
public const RAW_LOCALES_GLOBAL_BASE_URL = 'https://dev.sp-tarkov.com/SPT-AKI/Server/raw/branch/development/project/assets/database/locales/global/';
}

View File

@ -6,65 +6,97 @@ use App\Exceptions\ItemNotFoundException;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use App\Config\GiteaConfig;
use Illuminate\Support\Facades\Log;
class ItemsCollection
{
protected Collection $items;
protected Collection $locale;
protected Collection $locales;
public function __construct()
private string $items_cache_key = 'items';
private string $locales_cache_key = 'locales';
public function __construct() {
if (!Cache::has($this->items_cache_key)) {
$this->refreshItemsCache();
}
else $this->items = Cache::get($this->items_cache_key);
if (!Cache::has($this->locales_cache_key)) {
$this->refreshLocalesCache();
}
else $this->locales = Cache::get($this->locales_cache_key);
}
public function refreshLocalesCache(): void
{
if (!Cache::has('items')) {
$file = storage_path('items.json');
$this->items = collect(json_decode(file_get_contents($file), true)['data']);
Cache::put('items', $this->items);
} else {
$this->items = Cache::get('items');
$this->locales = collect();
$raw_locales_global_base_url = GiteaConfig::RAW_LOCALES_GLOBAL_BASE_URL;
// Getting all locales in project/assets/database/locales/global from the Server development branch repository
$locales_list = collect(json_decode(file_get_contents(GiteaConfig::LOCALES_GLOBAL_URL), true));
foreach($locales_list as $item) {
// Extract the json name for the locale
preg_match('/([a-z]{2}(-[a-z]{2})?).json/', $item['name'], $current_locale_name, PREG_OFFSET_CAPTURE);
// If the name is not supported for any reason, dont add it to the locales
if (empty($current_locale_name) || !$current_locale_name[1][0]) continue;
$trimmed_current_locale_name = trim($current_locale_name[1][0]);
$test = collect([$trimmed_current_locale_name => json_decode(file_get_contents("${raw_locales_global_base_url}/${trimmed_current_locale_name}.json"), true)['templates']]);
$this->locales = $this->locales->merge($test);
}
if (!Cache::has('locale')) {
$file = storage_path('locale.json');
$this->locale = collect(json_decode(file_get_contents($file), true)['templates']);
Cache::put('locale', $this->locale);
} else {
$this->locale = Cache::get('locale');
Cache::set($this->locales_cache_key, $this->locales);
}
public function refreshItemsCache(): void {
$this->items = collect(json_decode(file_get_contents(GiteaConfig::RAW_ITEMS_URL), true));
Cache::put($this->items_cache_key, $this->items);
}
public function refreshAllCache(): void {
$this->refreshItemsCache();
$this->refreshLocalesCache();
}
/**
* @param string $query
* @param string $query the content of the query eg. 'AK'
* @param string $locale the chosen local. Default to 'en'
* @return Collection
*/
public function findItem(string $query): Collection
public function findItem(string $query, string $locale = 'en'): Collection
{
return $this->items->filter(function ($val, $key) use ($query) {
return $this->items->filter(function ($val, $key) use ($query, $locale) {
$query = Str::lower($query);
return Str::contains($val['_id'], $query)
|| Str::contains($val['_name'], $query)
|| Str::contains($val['_parent'], $query)
|| (($this->locale[$key] ?? false)
&& $this->locale[$key]['Name']
&& Str::contains(Str::lower($this->locale[$key]['Name']), $query)
&& Str::contains(Str::lower($this->locale[$key]['ShortName']), $query));
})->map(function ($item) {
|| (($this->locales[$locale][$key] ?? false)
&& $this->locales[$locale][$key]['Name']
&& Str::contains(Str::lower($this->locale[$locale][$key]['Name']), $query)
&& Str::contains(Str::lower($this->locale[$locale][$key]['ShortName']), $query));
})->map(function ($item) use ($locale) {
return [
'_id' => $item['_id'],
'_name' => $item['_name'],
'locale' => $this->locale[$item['_id']] ?? ''
'locale' => $this->locales[$locale][$item['_id']] ?? ''
];
})->values();
}
/**
* @param string $id
* @param string $id the item ID to look for
* @param string $locale the chosen local. Default to 'en'
* @return array
* @throws ItemNotFoundException
*/
public function getItemById(string $id): array
public function getItemById(string $id, string $locale = 'en'): array
{
$item = $this->items[$id] ?? throw new ItemNotFoundException('Item not found');
return [
'item' => $item,
'locale' => $this->locale[$id] ?? ''
'locale' => $this->locales[$locale][$id] ?? ''
];
}
}

View File

@ -55,4 +55,21 @@ class ItemController extends Controller
], Response::HTTP_NOT_FOUND);
}
}
/**
* @param string $id
* @return JsonResponse
*/
public function refreshItems(): JsonResponse
{
try {
return response()->json($this->itemsCollection->getItemById($id));
} catch (Throwable $exception) {
Log::error($exception->getMessage());
Log::error($exception->getTraceAsString());
return response()->json([
'error' => 'Item not found.',
], Response::HTTP_NOT_FOUND);
}
}
}

View File

@ -17,5 +17,8 @@ $router->get('/', function () {
return view('app');
});
$router->get('/api/refresh', 'ItemController@refreshAllCache');
$router->post('/api/{locale}/search', 'ItemController@search');
$router->get('/api/item/{locale}/{id}', 'ItemController@getItem');
$router->post('/api/search', 'ItemController@search');
$router->get('/api/item/{id}', 'ItemController@getItem');