Skip to content

Commit

Permalink
#2595 WIP changes done to a route are kept in a separate table, to di…
Browse files Browse the repository at this point in the history
…splay later in the Teams function.
  • Loading branch information
Wotuu committed Oct 28, 2024
1 parent 06ed05e commit 5ed93e8
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 46 deletions.
27 changes: 22 additions & 5 deletions app/Http/Controllers/Ajax/AjaxDungeonRouteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Http\Controllers\Ajax;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Traits\ChangesDungeonRoute;
use App\Http\Controllers\Traits\ListsBrushlines;
use App\Http\Controllers\Traits\ListsDungeonFloorSwitchMarkers;
use App\Http\Controllers\Traits\ListsEnemies;
Expand Down Expand Up @@ -68,6 +69,7 @@ class AjaxDungeonRouteController extends Controller
use ListsEnemyPatrols;
use ListsMapIcons;
use ListsPaths;
use ChangesDungeonRoute;

/**
* @return mixed
Expand Down Expand Up @@ -238,11 +240,9 @@ public function htmlsearch(AjaxDungeonRouteSearchFormRequest $request, Expansion
'ratings', 'routeattributes', 'dungeon', 'dungeon.activeFloors', 'mappingVersion'])
->join('dungeons', 'dungeon_routes.dungeon_id', 'dungeons.id')
->join('mapping_versions', 'mapping_versions.dungeon_id', 'dungeons.id')
->when($expansion !== null, static fn(Builder $builder) =>
$builder->where('dungeons.expansion_id', $expansion->id)
->when($expansion !== null, static fn(Builder $builder) => $builder->where('dungeons.expansion_id', $expansion->id)
)
->when($season !== null, static fn(Builder $builder) =>
$builder->where('dungeon_routes.season_id', $season->id)
->when($season !== null, static fn(Builder $builder) => $builder->where('dungeon_routes.season_id', $season->id)
)
// Only non-try routes, combine both where() and whereNull(), there are inconsistencies where one or the
// other may work, this covers all bases for both dev and live
Expand Down Expand Up @@ -455,25 +455,34 @@ public function store(
): DungeonRoute {
$this->authorize('edit', $dungeonRoute);

$beforeDungeonRoute = null;

if ($dungeonRoute === null) {
$dungeonRoute = new DungeonRoute();
} else {
$beforeDungeonRoute = clone $dungeonRoute;
}

// Update or insert it
if (!$dungeonRoute->saveFromRequest($request, $seasonService, $expansionService, $thumbnailService)) {
abort(500, 'Unable to save dungeonroute');
}

$this->dungeonRouteChanged($dungeonRoute, $beforeDungeonRoute, $dungeonRoute);

return $dungeonRoute;
}

/**
* @throws AuthorizationException
* @throws Exception
*/
public function storePullGradient(Request $request, SeasonService $seasonService, DungeonRoute $dungeonRoute): Response
public function storePullGradient(Request $request, DungeonRoute $dungeonRoute): Response
{
$this->authorize('edit', $dungeonRoute);

$beforeDungeonRoute = clone $dungeonRoute;

$dungeonRoute->pull_gradient = $request->get('pull_gradient', '');
$dungeonRoute->pull_gradient_apply_always = $request->get('pull_gradient_apply_always', false);

Expand All @@ -482,6 +491,8 @@ public function storePullGradient(Request $request, SeasonService $seasonService
abort(500, 'Unable to save dungeonroute');
}

$this->dungeonRouteChanged($dungeonRoute, $beforeDungeonRoute, $dungeonRoute);

return response()->noContent();
}

Expand All @@ -496,6 +507,8 @@ public function delete(Request $request, DungeonRoute $dungeonRoute): Response
abort(500, 'Unable to delete dungeonroute');
}

$this->dungeonRouteChanged($dungeonRoute, $dungeonRoute, null);

return response()->noContent();
}

Expand All @@ -512,13 +525,17 @@ public function publishedState(PublishFormRequest $request, DungeonRoute $dungeo
abort(422, 'This sharing state is not available for this route');
}

$beforeDungeonRoute = clone $dungeonRoute;

$dungeonRoute->published_state_id = PublishedState::ALL[$publishedState];
if ($dungeonRoute->published_state_id === PublishedState::ALL[PublishedState::WORLD]) {
$dungeonRoute->published_at = date('Y-m-d H:i:s', time());
}

$dungeonRoute->save();

$this->dungeonRouteChanged($dungeonRoute, $beforeDungeonRoute, $dungeonRoute);

return response()->noContent();
}

Expand Down
65 changes: 65 additions & 0 deletions app/Http/Controllers/Traits/ChangesDungeonRoute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\Http\Controllers\Traits;

use App\Models\DungeonRoute\DungeonRoute;
use App\Models\DungeonRoute\DungeonRouteChange;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;

trait ChangesDungeonRoute
{
private const IGNORE_KEYS = ['updated_at'];

/**
* @param DungeonRoute $dungeonRoute
* @param Model|null $beforeModel
* @param Model|null $afterModel
* @throws Exception
*/
public function dungeonRouteChanged(DungeonRoute $dungeonRoute, ?Model $beforeModel, ?Model $afterModel): void
{
if ($beforeModel === null && $afterModel === null) {
throw new Exception('Must have at least a $beforeModel OR $afterModel');
}

$user = Auth::user();

$boolToInt = fn($value) => is_bool($value) ? (int)$value : $value;
$beforeAttributes = $beforeModel !== null ? array_map($boolToInt, $beforeModel->getAttributes()) : [];
$afterAttributes = $afterModel !== null ? array_map($boolToInt, $afterModel->getAttributes()) : [];

$changedKeys = $this->getChangedData($beforeAttributes, $afterAttributes, self::IGNORE_KEYS);

DungeonRouteChange::create([
'dungeon_route_id' => $dungeonRoute->id,
'user_id' => $user?->id,
'team_id' => $dungeonRoute->team_id,
'team_role' => $dungeonRoute->team?->getUserRole($user),
'model_id' => $beforeModel?->id ?? $afterModel->id,
'model_class' => ($beforeModel ?? $afterModel)::class,
'before' => $beforeModel !== null ? json_encode(array_intersect_key($beforeAttributes, $changedKeys)) : null,
'after' => $afterModel !== null ? json_encode(array_intersect_key($afterAttributes, $changedKeys)) : null,
]);
}

private function getChangedData(array $before, array $after, array $excludeKeys = []): array
{
$alteredKeys = [];
foreach ($before as $key => $value) {
if (in_array($key, $excludeKeys)) {
continue;
}

if ($value !== $after[$key]) {
$alteredKeys[$key] = [
'before' => $value,
'after' => $after[$key],
];
}
}

return $alteredKeys;
}
}
21 changes: 18 additions & 3 deletions app/Models/DungeonRoute/DungeonRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ class DungeonRoute extends Model

protected $casts = [
'enemy_forces' => 'integer',
'demo' => 'integer',
'level_min' => 'integer',
'level_max' => 'integer',
];

/**
Expand Down Expand Up @@ -767,8 +770,8 @@ public function saveTemporaryFromRequest(
// Can still be null if there are no seasons for this dungeon, like in Classic
$this->season_id = $activeSeason->id ?? null;

$this->faction_id = 1;
$this->difficulty = 1;
$this->faction_id = 1;
// $this->difficulty = 1;
$this->seasonal_index = 0;
$this->teeming = 0;

Expand All @@ -788,6 +791,12 @@ public function saveTemporaryFromRequest(
$this->level_min = $this->level_min ?? $activeSeason->key_level_min;
$this->level_max = $this->level_max ?? $activeSeason->key_level_max;
}
if ($this->level_min !== null) {
$this->level_min = (int)$this->level_min;
}
if ($this->level_max !== null) {
$this->level_max = (int)$this->level_max;
}

$this->expires_at = Carbon::now()->addHours(config('keystoneguru.sandbox_dungeon_route_expires_hours'))->toDateTimeString();

Expand Down Expand Up @@ -839,7 +848,7 @@ public function saveFromRequest(
$this->season_id = $activeSeason->id ?? null;

//$this->difficulty = $request->get('difficulty', $this->difficulty);
$this->difficulty = 1;
// $this->difficulty = 1;
$this->seasonal_index = (int)$request->get('seasonal_index', [$this->seasonal_index])[0];
$this->teeming = 0; // (int)$request->get('teeming', $this->teeming) ?? 0;

Expand All @@ -864,6 +873,12 @@ public function saveFromRequest(
$this->level_min = $this->level_min ?? $activeSeason->key_level_min;
$this->level_max = $this->level_max ?? $activeSeason->key_level_max;
}
if ($this->level_min !== null) {
$this->level_min = (int)$this->level_min;
}
if ($this->level_max !== null) {
$this->level_max = (int)$this->level_max;
}

if ($user?->hasRole(Role::ROLE_ADMIN)) {
$this->demo = intval($request->get('demo', 0)) > 0;
Expand Down
62 changes: 62 additions & 0 deletions app/Models/DungeonRoute/DungeonRouteChange.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\Models\DungeonRoute;

use App\Models\Team;
use App\Models\Traits\HasGenericModelRelation;
use App\Models\User;
use Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon;

/**
* @property int $id
* @property int $dungeon_route_id
* @property int|null $user_id
* @property int|null $team_id
* @property int|null $team_role
* @property int $model_id
* @property string $model_class
* @property array|null $before
* @property array|null $after
*
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
*
* @mixin Eloquent
*/
class DungeonRouteChange extends Model
{
use HasGenericModelRelation;

protected $fillable = [
'dungeon_route_id',
'user_id',
'team_id',
'team_role',
'model_class',
'before',
'after',
];

protected $casts = [
'before' => 'array',
'after' => 'array',
];

public function dungeonRoute(): BelongsTo
{
return $this->belongsTo(DungeonRoute::class);
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}

public function team(): BelongsTo
{
return $this->belongsTo(Team::class);
}
}
Loading

0 comments on commit 5ed93e8

Please sign in to comment.