mass update
This commit is contained in:
@@ -295,6 +295,7 @@ class BackendApi {
|
||||
String? storyline,
|
||||
String? coverUrl,
|
||||
int? releaseYear,
|
||||
bool? locked,
|
||||
}) async {
|
||||
final map = await _post({
|
||||
'action': 'set_game_status',
|
||||
@@ -309,6 +310,7 @@ class BackendApi {
|
||||
if (storyline != null) 'storyline': storyline,
|
||||
if (coverUrl != null) 'cover_url': coverUrl,
|
||||
if (releaseYear != null) 'release_year': releaseYear,
|
||||
if (locked != null) 'locked': locked,
|
||||
});
|
||||
return (map['game'] as Map).cast<String, dynamic>();
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
test
|
||||
@@ -11,6 +11,7 @@ class Game {
|
||||
final String? summary;
|
||||
final String? coverUrl;
|
||||
final int? releaseYear;
|
||||
final bool locked;
|
||||
|
||||
Game({
|
||||
required this.id,
|
||||
@@ -23,6 +24,7 @@ class Game {
|
||||
this.summary,
|
||||
this.coverUrl,
|
||||
this.releaseYear,
|
||||
this.locked = false,
|
||||
});
|
||||
|
||||
factory Game.fromJson(Map<String, dynamic> j) {
|
||||
@@ -37,6 +39,7 @@ class Game {
|
||||
summary: j['loc_summary'] as String?,
|
||||
coverUrl: j['cover_url'] as String?,
|
||||
releaseYear: (j['release_year'] as num?)?.toInt(),
|
||||
locked: ((j['loc_locked'] ?? j['locked'] ?? 0) as num?)?.toInt() == 1,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,14 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
late Game _game;
|
||||
late ItemStatus _status;
|
||||
late ItemStatus _origStatus;
|
||||
late TextEditingController _titleCtrl;
|
||||
late TextEditingController _summaryCtrl;
|
||||
String _title = '';
|
||||
String _summary = '';
|
||||
late String _origTitle;
|
||||
late String _origSummary;
|
||||
bool _lockTexts = false;
|
||||
late bool _origLocked;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -26,13 +34,52 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
_game = widget.game;
|
||||
_status = widget.game.status;
|
||||
_origStatus = widget.game.status;
|
||||
_title = (widget.game.localizedTitle?.isNotEmpty ?? false) ? widget.game.localizedTitle! : widget.game.name;
|
||||
_summary = widget.game.summary ?? '';
|
||||
_lockTexts = widget.game.locked;
|
||||
_origTitle = _title;
|
||||
_origSummary = _summary;
|
||||
_origLocked = _lockTexts;
|
||||
_titleCtrl = TextEditingController(text: _title);
|
||||
_summaryCtrl = TextEditingController(text: _summary);
|
||||
_titleCtrl.addListener(() {
|
||||
final v = _titleCtrl.text;
|
||||
if (v != _title) {
|
||||
setState(() {
|
||||
_title = v;
|
||||
});
|
||||
}
|
||||
});
|
||||
_summaryCtrl.addListener(() {
|
||||
final v = _summaryCtrl.text;
|
||||
if (v != _summary) {
|
||||
setState(() {
|
||||
_summary = v;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool get _dirty => _status != _origStatus;
|
||||
@override
|
||||
void dispose() {
|
||||
_titleCtrl.dispose();
|
||||
_summaryCtrl.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get _dirty => _status != _origStatus || _title != _origTitle || _summary != _origSummary;
|
||||
bool get _lockedDirty => _lockTexts != _origLocked;
|
||||
bool get _isDirty => _dirty || _lockedDirty;
|
||||
|
||||
bool _hasCustomTexts(String title, String summary) {
|
||||
return title.trim().isNotEmpty || summary.trim().isNotEmpty;
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
try {
|
||||
final title = _title.trim();
|
||||
final summary = _summary.trim();
|
||||
final backend = ref.read(backendApiProvider);
|
||||
await backend.setGameStatus(
|
||||
igdbId: _game.igdbId,
|
||||
@@ -40,13 +87,36 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
originalName: _game.originalName,
|
||||
status: _status.index,
|
||||
lang: 'de',
|
||||
title: _game.localizedTitle ?? _game.name,
|
||||
summary: _game.summary,
|
||||
title: title.isNotEmpty ? title : _game.name,
|
||||
summary: summary,
|
||||
coverUrl: _game.coverUrl,
|
||||
releaseYear: _game.releaseYear,
|
||||
locked: _lockTexts,
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() => _origStatus = _status);
|
||||
setState(() {
|
||||
_game = Game(
|
||||
id: _game.id,
|
||||
igdbId: _game.igdbId,
|
||||
name: _game.name,
|
||||
localizedTitle: title.isNotEmpty ? title : null,
|
||||
originalName: _game.originalName,
|
||||
status: _status,
|
||||
note: _game.note,
|
||||
summary: summary.isNotEmpty ? summary : null,
|
||||
coverUrl: _game.coverUrl,
|
||||
releaseYear: _game.releaseYear,
|
||||
locked: _lockTexts,
|
||||
);
|
||||
_title = title;
|
||||
_summary = summary;
|
||||
_titleCtrl.text = title;
|
||||
_summaryCtrl.text = summary;
|
||||
_origStatus = _status;
|
||||
_origTitle = title;
|
||||
_origSummary = summary;
|
||||
_origLocked = _lockTexts;
|
||||
});
|
||||
// ignore: unused_result
|
||||
ref.invalidate(gamesStreamProvider);
|
||||
// ignore: unused_result
|
||||
@@ -75,7 +145,7 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: _dirty
|
||||
floatingActionButton: _isDirty
|
||||
? FloatingActionButton.extended(
|
||||
onPressed: _save,
|
||||
icon: const Icon(Icons.save),
|
||||
@@ -123,7 +193,24 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
children: [
|
||||
_header(context, g),
|
||||
const SizedBox(height: 16),
|
||||
if ((g.summary ?? '').isNotEmpty) _summaryCard(context, g.summary!),
|
||||
_summaryCard(context),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _lockTexts,
|
||||
onChanged: (v) => setState(() => _lockTexts = v ?? false),
|
||||
checkColor: Colors.white,
|
||||
side: const BorderSide(color: Colors.white70),
|
||||
),
|
||||
const Expanded(
|
||||
child: Text(
|
||||
'Eigene Texte vor Updates schützen',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -160,10 +247,26 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
g.releaseYear != null ? '${g.displayName} (${g.releaseYear})' : g.displayName,
|
||||
TextField(
|
||||
controller: _titleCtrl,
|
||||
maxLines: 2,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: Colors.white),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Titel (DE)',
|
||||
labelStyle: const TextStyle(color: Colors.white70),
|
||||
hintText: g.displayName,
|
||||
hintStyle: const TextStyle(color: Colors.white54),
|
||||
enabledBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
|
||||
focusedBorder: const UnderlineInputBorder(borderSide: BorderSide(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
if (g.releaseYear != null) ...[
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'Erscheinungsjahr: ${g.releaseYear}',
|
||||
style: const TextStyle(color: Colors.white70),
|
||||
),
|
||||
],
|
||||
if (g.originalName != null && g.originalName!.isNotEmpty) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
@@ -182,7 +285,7 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _summaryCard(BuildContext context, String summary) {
|
||||
Widget _summaryCard(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
@@ -195,9 +298,29 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Beschreibung', style: Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.white)),
|
||||
Text('Beschreibung (DE)', style: Theme.of(context).textTheme.titleMedium?.copyWith(color: Colors.white)),
|
||||
const SizedBox(height: 6),
|
||||
Text(summary),
|
||||
TextField(
|
||||
controller: _summaryCtrl,
|
||||
maxLines: null,
|
||||
minLines: 4,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Beschreibung bearbeiten',
|
||||
hintStyle: const TextStyle(color: Colors.white54),
|
||||
filled: true,
|
||||
fillColor: Colors.black12,
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: const BorderSide(color: Colors.white30),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderSide: BorderSide(color: Theme.of(context).colorScheme.primary),
|
||||
),
|
||||
contentPadding: const EdgeInsets.all(12),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -228,8 +351,11 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
final cover = (data['cover'] is Map && data['cover']['image_id'] != null)
|
||||
? 'https://images.igdb.com/igdb/image/upload/t_cover_big/${data['cover']['image_id']}.jpg'
|
||||
: _game.coverUrl;
|
||||
final summary = data['summary'] as String? ?? _game.summary;
|
||||
final title = data['name'] as String? ?? _game.name;
|
||||
final igdbSummary = data['summary'] as String? ?? '';
|
||||
final igdbTitle = data['name'] as String? ?? '';
|
||||
// If not locked, always replace with fresh IGDB texts
|
||||
final summary = _lockTexts ? _summary : igdbSummary;
|
||||
final title = _lockTexts ? _title : (igdbTitle.isNotEmpty ? igdbTitle : _title);
|
||||
final firstRelease = data['first_release_date'];
|
||||
int? year;
|
||||
if (firstRelease is num) {
|
||||
@@ -237,16 +363,18 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
}
|
||||
|
||||
await ref.read(backendApiProvider).setGameStatus(
|
||||
igdbId: _game.igdbId,
|
||||
name: title,
|
||||
originalName: _game.originalName,
|
||||
status: _status.index,
|
||||
lang: 'de',
|
||||
title: title,
|
||||
summary: summary,
|
||||
coverUrl: cover,
|
||||
releaseYear: year,
|
||||
);
|
||||
igdbId: _game.igdbId,
|
||||
name: title,
|
||||
originalName: _game.originalName,
|
||||
status: _status.index,
|
||||
lang: 'de',
|
||||
// Wenn nicht gesperrt, die aktuellen Texte (aus IGDB oder lokal) zurückschreiben
|
||||
title: title,
|
||||
summary: summary,
|
||||
coverUrl: cover,
|
||||
releaseYear: year,
|
||||
locked: _lockTexts,
|
||||
);
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
@@ -261,7 +389,16 @@ class _GamesDetailScreenState extends ConsumerState<GamesDetailScreen> {
|
||||
summary: summary,
|
||||
coverUrl: cover,
|
||||
releaseYear: year ?? _game.releaseYear,
|
||||
locked: _lockTexts,
|
||||
);
|
||||
_title = title;
|
||||
_summary = summary;
|
||||
_origTitle = _title;
|
||||
_origSummary = _summary;
|
||||
_titleCtrl.text = _title;
|
||||
_summaryCtrl.text = _summary;
|
||||
_origStatus = _status;
|
||||
_origLocked = _lockTexts;
|
||||
});
|
||||
// ignore: unused_result
|
||||
ref.invalidate(gamesStreamProvider);
|
||||
|
||||
@@ -38,17 +38,27 @@ class GamesScreen extends ConsumerWidget {
|
||||
onChanged: (f) => ref.read(gameFilterProvider.notifier).state = f,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Neue Spiele hinzufügen'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (_) => const GamesAddScreen()),
|
||||
);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.update),
|
||||
label: const Text('Alle Spiele updaten'),
|
||||
onPressed: gamesAsync is AsyncData<List<Game>> && (gamesAsync.value?.isNotEmpty ?? false)
|
||||
? () => _updateAllGames(context, ref, gamesAsync.value ?? const [])
|
||||
: null,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Neue Spiele hinzufügen'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (_) => const GamesAddScreen()),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
@@ -130,8 +140,10 @@ class GamesScreen extends ConsumerWidget {
|
||||
final cover = (data['cover'] is Map && data['cover']['image_id'] != null)
|
||||
? 'https://images.igdb.com/igdb/image/upload/t_cover_big/${data['cover']['image_id']}.jpg'
|
||||
: g.coverUrl;
|
||||
final summary = data['summary'] as String? ?? g.summary;
|
||||
final title = data['name'] as String? ?? g.name;
|
||||
final summary = g.locked ? (g.summary ?? '') : (data['summary'] as String? ?? g.summary ?? '');
|
||||
final title = g.locked
|
||||
? (g.localizedTitle?.isNotEmpty == true ? g.localizedTitle! : g.name)
|
||||
: (data['name'] as String? ?? g.name);
|
||||
final fr = data['first_release_date'];
|
||||
int? year;
|
||||
if (fr is num) {
|
||||
@@ -147,6 +159,7 @@ class GamesScreen extends ConsumerWidget {
|
||||
summary: summary,
|
||||
coverUrl: cover,
|
||||
releaseYear: year,
|
||||
locked: g.locked,
|
||||
);
|
||||
// ignore: unused_result
|
||||
ref.invalidate(gamesStreamProvider);
|
||||
@@ -158,6 +171,98 @@ class GamesScreen extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateAllGames(BuildContext context, WidgetRef ref, List<Game> games) async {
|
||||
if (games.isEmpty) return;
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
int idx = 0;
|
||||
int ok = 0;
|
||||
int fail = 0;
|
||||
String current = '';
|
||||
final total = games.length;
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (ctx) {
|
||||
return StatefulBuilder(builder: (ctx, setState) {
|
||||
Future<void> run() async {
|
||||
try {
|
||||
for (final g in games) {
|
||||
idx++;
|
||||
current = g.displayName;
|
||||
setState(() {});
|
||||
try {
|
||||
final igdb = ref.read(igdbApiProvider);
|
||||
final data = await igdb.getGameDetails(g.igdbId, lang: 'de');
|
||||
final cover = (data['cover'] is Map && data['cover']['image_id'] != null)
|
||||
? 'https://images.igdb.com/igdb/image/upload/t_cover_big/${data['cover']['image_id']}.jpg'
|
||||
: g.coverUrl;
|
||||
final summary = g.locked ? (g.summary ?? '') : (data['summary'] as String? ?? g.summary ?? '');
|
||||
final title = g.locked
|
||||
? (g.localizedTitle?.isNotEmpty == true ? g.localizedTitle! : g.name)
|
||||
: (data['name'] as String? ?? g.name);
|
||||
final fr = data['first_release_date'];
|
||||
int? year;
|
||||
if (fr is num) {
|
||||
year = DateTime.fromMillisecondsSinceEpoch(fr.toInt() * 1000).year;
|
||||
}
|
||||
await ref.read(backendApiProvider).setGameStatus(
|
||||
igdbId: g.igdbId,
|
||||
name: title,
|
||||
originalName: g.originalName,
|
||||
status: g.status.index,
|
||||
lang: 'de',
|
||||
title: title,
|
||||
summary: summary,
|
||||
coverUrl: cover,
|
||||
releaseYear: year,
|
||||
locked: g.locked,
|
||||
);
|
||||
ok++;
|
||||
} catch (_) {
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
// ignore: unused_result
|
||||
ref.invalidate(gamesStreamProvider);
|
||||
// ignore: unused_result
|
||||
ref.invalidate(gamesProvider);
|
||||
messenger.showSnackBar(SnackBar(content: Text('Alle Spiele aktualisiert: $ok/$total (Fehler: $fail)')));
|
||||
} finally {
|
||||
if (ctx.mounted) Navigator.of(ctx).pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == 0 && ok == 0 && fail == 0) {
|
||||
// ignore: discarded_futures
|
||||
run();
|
||||
}
|
||||
|
||||
final progress = total > 0 ? ((idx / total).clamp(0, 1)).toDouble() : null;
|
||||
return AlertDialog(
|
||||
title: const Text('Alle Spiele updaten'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Aktualisiere: $idx / $total'),
|
||||
if (current.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
current,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
LinearProgressIndicator(value: progress),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _deleteGame(BuildContext context, WidgetRef ref, Game g) async {
|
||||
final ok = await showDialog<bool>(
|
||||
context: context,
|
||||
|
||||
+26
-11
@@ -161,26 +161,33 @@ function getLocalization(int $igdbId, string $lang = 'de'): ?array {
|
||||
return $row ?: null;
|
||||
}
|
||||
|
||||
function saveLocalization(int $igdbId, string $lang, ?string $title, ?string $summary, ?string $storyline, ?int $userId): array {
|
||||
function saveLocalization(int $igdbId, string $lang, ?string $title, ?string $summary, ?string $storyline, ?int $userId, ?int $locked = null): array {
|
||||
$pdo = getDb();
|
||||
$existing = getLocalization($igdbId, $lang);
|
||||
$lockedVal = $locked === null ? (int)($existing['locked'] ?? 0) : (int)!!$locked;
|
||||
$titleToSave = $title !== null ? $title : ($existing['title'] ?? null);
|
||||
$summaryToSave = $summary !== null ? $summary : ($existing['summary'] ?? null);
|
||||
$storyToSave = $storyline !== null ? $storyline : ($existing['storyline'] ?? null);
|
||||
$sql = '
|
||||
INSERT INTO igdb_localizations (igdb_id, lang, title, summary, storyline, user_id)
|
||||
VALUES (:id, :lang, :title, :summary, :storyline, :user_id)
|
||||
INSERT INTO igdb_localizations (igdb_id, lang, title, summary, storyline, user_id, locked)
|
||||
VALUES (:id, :lang, :title, :summary, :storyline, :user_id, :locked)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
title = VALUES(title),
|
||||
summary = VALUES(summary),
|
||||
storyline = VALUES(storyline),
|
||||
user_id = VALUES(user_id),
|
||||
locked = VALUES(locked),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
':id' => $igdbId,
|
||||
':lang' => $lang,
|
||||
':title' => $title,
|
||||
':summary' => $summary,
|
||||
':storyline' => $storyline,
|
||||
':title' => $titleToSave,
|
||||
':summary' => $summaryToSave,
|
||||
':storyline' => $storyToSave,
|
||||
':user_id' => $userId,
|
||||
':locked' => $lockedVal,
|
||||
]);
|
||||
return getLocalization($igdbId, $lang);
|
||||
}
|
||||
@@ -498,10 +505,11 @@ if (isset($_GET['action'])) {
|
||||
$game['my_note'] = null;
|
||||
}
|
||||
$hasLoc = false;
|
||||
$locLocked = 0;
|
||||
if ($lang !== 'en') {
|
||||
$loc = getLocalization($id, $lang);
|
||||
if ($loc !== null) {
|
||||
$hasLoc = true;
|
||||
$locLocked = (int)($loc['locked'] ?? 0);
|
||||
if (!empty($loc['title'])) $game['name'] = $loc['title'];
|
||||
if (!empty($loc['summary'])) $game['summary'] = $loc['summary'];
|
||||
if (!empty($loc['storyline'])) $game['storyline'] = $loc['storyline'];
|
||||
@@ -509,15 +517,20 @@ if (isset($_GET['action'])) {
|
||||
'lang' => $lang,
|
||||
'source' => 'custom',
|
||||
'id' => $loc['id'],
|
||||
'locked' => $locLocked,
|
||||
];
|
||||
if ($locLocked === 1) {
|
||||
$hasLoc = true; // locked -> treat as authoritative, skip external fallback
|
||||
}
|
||||
}
|
||||
}
|
||||
$game['has_localization'] = $hasLoc;
|
||||
$game['loc_locked'] = $locLocked;
|
||||
$game['has_external_de'] = false;
|
||||
$game['external_de_source']= null;
|
||||
$game['external_de_summary']= null;
|
||||
$game['external_de_url'] = null;
|
||||
if ($checkExternal && $lang === 'de' && !$hasLoc) {
|
||||
if ($checkExternal && $lang === 'de' && $locLocked === 0) {
|
||||
$wiki = wikiFetchGermanSummaryForTitle($game['name']);
|
||||
if ($wiki !== null && !empty($wiki['extract'])) {
|
||||
$game['has_external_de'] = true;
|
||||
@@ -1067,7 +1080,8 @@ try {
|
||||
CASE g.status WHEN 1 THEN 'Progress' WHEN 2 THEN 'Done' ELSE 'Init' END AS status,
|
||||
loc.title AS loc_title,
|
||||
loc.summary AS loc_summary,
|
||||
loc.storyline AS loc_storyline
|
||||
loc.storyline AS loc_storyline,
|
||||
loc.locked AS loc_locked
|
||||
FROM game g
|
||||
LEFT JOIN igdb_localizations loc
|
||||
ON loc.igdb_id = g.igdb_id AND loc.lang = ?
|
||||
@@ -1333,6 +1347,7 @@ try {
|
||||
$locTitle = isset($in['title']) ? trim($in['title']) : '';
|
||||
$locSummary = isset($in['summary']) ? trim($in['summary']) : '';
|
||||
$locStory = isset($in['storyline']) ? trim($in['storyline']) : '';
|
||||
$lockFlag = array_key_exists('locked', $in) ? (int)!!$in['locked'] : null;
|
||||
$coverUrl = isset($in['cover_url']) ? trim($in['cover_url']) : null;
|
||||
$releaseYear = isset($in['release_year']) ? (int)$in['release_year'] : null;
|
||||
$GLOBALS['__release_year'] = $releaseYear;
|
||||
@@ -1340,8 +1355,8 @@ try {
|
||||
if ($name === '') fail('Missing "name"');
|
||||
if ($status < 0 || $status > 2) fail('Invalid "status" (0,1,2)');
|
||||
$game = saveGameStatus($igdbId, $name, $orig !== '' ? $orig : null, $status, $note !== '' ? $note : null, $coverUrl ?: null);
|
||||
if ($locTitle !== '' || $locSummary !== '' || $locStory !== '') {
|
||||
saveLocalization($igdbId, $lang, $locTitle ?: null, $locSummary ?: null, $locStory ?: null, null);
|
||||
if ($locTitle !== '' || $locSummary !== '' || $locStory !== '' || $lockFlag !== null) {
|
||||
saveLocalization($igdbId, $lang, $locTitle ?: null, $locSummary ?: null, $locStory ?: null, null, $lockFlag);
|
||||
}
|
||||
resp(['ok' => true, 'game' => $game]);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user