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\Collection;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use App\Config\GiteaConfig;
use Illuminate\Support\Facades\Log;
class ItemsCollection class ItemsCollection
{ {
protected Collection $items; 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')) { $this->locales = collect();
$file = storage_path('items.json'); $raw_locales_global_base_url = GiteaConfig::RAW_LOCALES_GLOBAL_BASE_URL;
$this->items = collect(json_decode(file_get_contents($file), true)['data']);
Cache::put('items', $this->items); // Getting all locales in project/assets/database/locales/global from the Server development branch repository
} else { $locales_list = collect(json_decode(file_get_contents(GiteaConfig::LOCALES_GLOBAL_URL), true));
$this->items = Cache::get('items'); 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')) { Cache::set($this->locales_cache_key, $this->locales);
$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');
} }
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 * @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); $query = Str::lower($query);
return Str::contains($val['_id'], $query) return Str::contains($val['_id'], $query)
|| Str::contains($val['_name'], $query) || Str::contains($val['_name'], $query)
|| Str::contains($val['_parent'], $query) || Str::contains($val['_parent'], $query)
|| (($this->locale[$key] ?? false) || (($this->locales[$locale][$key] ?? false)
&& $this->locale[$key]['Name'] && $this->locales[$locale][$key]['Name']
&& Str::contains(Str::lower($this->locale[$key]['Name']), $query) && Str::contains(Str::lower($this->locale[$locale][$key]['Name']), $query)
&& Str::contains(Str::lower($this->locale[$key]['ShortName']), $query)); && Str::contains(Str::lower($this->locale[$locale][$key]['ShortName']), $query));
})->map(function ($item) { })->map(function ($item) use ($locale) {
return [ return [
'_id' => $item['_id'], '_id' => $item['_id'],
'_name' => $item['_name'], '_name' => $item['_name'],
'locale' => $this->locale[$item['_id']] ?? '' 'locale' => $this->locales[$locale][$item['_id']] ?? ''
]; ];
})->values(); })->values();
} }
/** /**
* @param string $id * @param string $id the item ID to look for
* @param string $locale the chosen local. Default to 'en'
* @return array * @return array
* @throws ItemNotFoundException * @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'); $item = $this->items[$id] ?? throw new ItemNotFoundException('Item not found');
return [ return [
'item' => $item, '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); ], 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'); 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->post('/api/search', 'ItemController@search');
$router->get('/api/item/{id}', 'ItemController@getItem'); $router->get('/api/item/{id}', 'ItemController@getItem');