Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/Http/Controllers/WikisController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public function getWikisOwnedByCurrentUser(Request $request): Response {
->user()
->managesWikis()
->withExists('pendingReviewSubmission as has_pending_review')
->with('latestSuspension')
->get();

return response(
Expand Down
8 changes: 8 additions & 0 deletions app/Wiki.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* @property int $is_featured
* @property string|null $wiki_deletion_reason
* @property-read mixed $domain_decoded
* @property-read WikiSuspension|null $latestSuspension
* @property-read ReviewSubmission|null $pendingReviewSubmission
* @property-read Collection<int, ReviewSubmission> $reviewSubmissions
* @property-read int|null $review_submissions_count
Expand Down Expand Up @@ -97,6 +98,13 @@ public function pendingReviewSubmission(): HasOne {
return $this->hasOne(ReviewSubmission::class)->pending();
}

/**
* Get latest suspension or `null`.
*/
public function latestSuspension(): HasOne {
return $this->hasOne(WikiSuspension::class)->latestOfMany();
}

public function wikiDbVersion() {
return $this->hasOne(WikiDb::class)->select(['id', 'wiki_id', 'version']);
}
Expand Down
11 changes: 11 additions & 0 deletions app/WikiSuspension.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Enums\WikiSuspensionReason;
use Carbon\CarbonImmutable;
use Database\Factories\WikiSuspensionFactory;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
Expand All @@ -21,9 +22,11 @@
* @property CarbonImmutable|null $created_at
* @property CarbonImmutable|null $updated_at
* @property-read User|null $actor
* @property-read bool $is_active
* @property-read ReviewSubmissionAction|null $reviewSubmissionAction
* @property-read Wiki|null $wiki
*
* @method static \Database\Factories\WikiSuspensionFactory factory($count = null, $state = [])
* @method static \Illuminate\Database\Eloquent\Builder<static>|WikiSuspension newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WikiSuspension newQuery()
* @method static \Illuminate\Database\Eloquent\Builder<static>|WikiSuspension query()
Expand All @@ -42,6 +45,8 @@ class WikiSuspension extends Model {
/** @use HasFactory<WikiSuspensionFactory> */
use HasFactory;

protected $appends = ['is_active'];

protected function casts() {
return [
'reason' => WikiSuspensionReason::class,
Expand All @@ -52,6 +57,12 @@ protected function casts() {
];
}

protected function isActive(): Attribute {
return Attribute::make(
get: fn (mixed $value, array $attributes): bool => CarbonImmutable::now()->gte($attributes['active_from']),
);
}

public function actor(): BelongsTo {
return $this->belongsTo(User::class, 'actor_user_id');
}
Expand Down
8 changes: 8 additions & 0 deletions tests/Feature/Models/WikiSuspensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,12 @@ public function testDatesAndTimesCastCorrectly(): void {
$this->assertInstanceOf(CarbonImmutable::class, $suspension->created_at);
$this->assertInstanceOf(CarbonImmutable::class, $suspension->updated_at);
}

public function testActiveAccessor(): void {
$suspensionAlreadyActive = WikiSuspension::factory()->create(['active_from' => now()->subDay()]);
$suspensionNotActive = WikiSuspension::factory()->create(['active_from' => now()->addDay()]);

$this->assertTrue($suspensionAlreadyActive->is_active);
$this->assertFalse($suspensionNotActive->is_active);
}
}
47 changes: 47 additions & 0 deletions tests/Feature/Models/WikiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Enums\UserRole;
use App\ReviewSubmission;
use App\Wiki;
use App\WikiSuspension;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

Expand Down Expand Up @@ -69,4 +70,50 @@ public function testCancelledReviewSubmissionIsNotPending(): void {

$this->assertNull(Wiki::findOrFail($wiki->id)->pendingReviewSubmission);
}

public function testLatestSuspendSuspensionIsNullWithNoSuspensions(): void {
$wiki = Wiki::factory()->create();

// Create a suspension for a different wiki to make sure it isn't returned by $wiki->latestSuspension
WikiSuspension::factory()->create();

$this->assertNull(Wiki::findOrFail($wiki->id)->latestSuspension);
}

public function testLatestSuspendSuspensionReturnsLatestSuspensionForTheGivenWiki(): void {
$wiki = Wiki::factory()->create();

// Create two suspensions for $wiki
WikiSuspension::factory()->for($wiki)->create();
$latestSuspension = WikiSuspension::factory()->for($wiki)->create();

// Create a suspension for a different wiki after the $latestSuspension
WikiSuspension::factory()->create();

$this->assertTrue(Wiki::findOrFail($wiki->id)->latestSuspension->is($latestSuspension));
}

public function testLatestSuspendSuspensionActionReturnsSuspensionScheduledInTheFuture(): void {
$wiki = Wiki::factory()->create();

WikiSuspension::factory()
->for($wiki)
->create(['active_from' => now()->addWeek()]);
$latestSuspension = WikiSuspension::factory()
->for($wiki)
->create(['active_from' => now()->addMonth()]);

$this->assertTrue(Wiki::findOrFail($wiki->id)->latestSuspension->is($latestSuspension));
}

public function testLatestSuspendSuspensionActionReturnsSuspensionScheduledInThePast(): void {
$wiki = Wiki::factory()->create();

WikiSuspension::factory()->for($wiki)->create();
$latestSuspension = WikiSuspension::factory()
->for($wiki)
->create(['active_from' => now()->subMonth()]);

$this->assertTrue(Wiki::findOrFail($wiki->id)->latestSuspension->is($latestSuspension));
}
}
29 changes: 29 additions & 0 deletions tests/Routes/Wiki/MineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\User;
use App\Wiki;
use App\WikiManager;
use App\WikiSuspension;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Config;
use Tests\Routes\Traits\OptionsRequestAllowed;
Expand Down Expand Up @@ -82,4 +83,32 @@ public function testMineIncludesPendingReviewSubmissions() {
['id' => $wikiWithApprovedSubmission->id, 'has_pending_review' => false],
]]);
}

public function testMineIncludesScheduledSuspensions() {
$wikiManagerUser = User::factory()->create(['verified' => true]);

$wikiWithNoSuspensions = Wiki::factory()
->has(WikiManager::factory())
->recycle($wikiManagerUser)
->create();

$wikiWithSuspension = Wiki::factory()
->has(WikiManager::factory())
->recycle($wikiManagerUser)
->create();
$suspension = WikiSuspension::factory()
->for($wikiWithSuspension)
->create();

$this->actingAs($wikiManagerUser, 'api')
->json('POST', $this->route, [])
->assertStatus(200)
->assertJson(['wikis' => [
['id' => $wikiWithNoSuspensions->id, 'latest_suspension' => null],
['id' => $wikiWithSuspension->id, 'latest_suspension' => [
'id' => $suspension->id,
'is_active' => true,
]],
]]);
}
}
Loading