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
38 changes: 38 additions & 0 deletions app/GraphQL/Mutations/CreatePinnedTestMeasurement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace App\GraphQL\Mutations;

use App\Models\PinnedTestMeasurement;
use App\Models\Project;
use Illuminate\Support\Facades\Gate;

final class CreatePinnedTestMeasurement extends AbstractMutation
{
public ?PinnedTestMeasurement $pinnedTestMeasurement = null;

/**
* @param array{
* projectId: int,
* name: string,
* } $args
*/
protected function mutate(array $args): void
{
$project = Project::find((int) $args['projectId']);
Gate::authorize('createPinnedTestMeasurement', $project);

$nextAvailablePosition = $project?->pinnedTestMeasurements()->max('position');
if ($nextAvailablePosition === null) {
$nextAvailablePosition = 1;
} else {
$nextAvailablePosition++;
}

$this->pinnedTestMeasurement = $project?->pinnedTestMeasurements()->create([
'name' => $args['name'],
'position' => $nextAvailablePosition,
]);
}
}
25 changes: 25 additions & 0 deletions app/GraphQL/Mutations/DeletePinnedTestMeasurement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace App\GraphQL\Mutations;

use App\Models\PinnedTestMeasurement;
use Illuminate\Support\Facades\Gate;

final class DeletePinnedTestMeasurement extends AbstractMutation
{
/**
* @param array{
* id: int,
* } $args
*/
protected function mutate(array $args): void
{
$measurement = PinnedTestMeasurement::find((int) $args['id']);

Gate::authorize('deletePinnedTestMeasurement', $measurement?->project);

$measurement?->delete();
}
}
58 changes: 58 additions & 0 deletions app/GraphQL/Mutations/UpdatePinnedTestMeasurementOrder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace App\GraphQL\Mutations;

use App\Models\PinnedTestMeasurement;
use App\Models\Project;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Gate;

final class UpdatePinnedTestMeasurementOrder extends AbstractMutation
{
/** @var ?Collection<PinnedTestMeasurement> */
public ?Collection $pinnedTestMeasurements = null;

/**
* @param array{
* projectId: int,
* pinnedTestMeasurementIds: array<int>,
* } $args
*/
protected function mutate(array $args): void
{
$project = Project::find((int) $args['projectId']);
Gate::authorize('updatePinnedTestMeasurementOrder', $project);

$projectMeasurementIds = $project?->pinnedTestMeasurements()->pluck('id');
$newOrder = collect($args['pinnedTestMeasurementIds']);

if ($projectMeasurementIds->diff($newOrder)->isNotEmpty()) {
throw new Exception('IDs for all PinnedTestMeasurements must be provided.');
}

if ($newOrder->count() !== $projectMeasurementIds->count()) {
throw new Exception('Provided set cannot contain duplicate IDs.');
}

if ($newOrder->isEmpty()) {
throw new Exception("Can't order an empty set.");
}

// We start at the previous maximum ID + 1 to guarantee that there are never any conflicts.
// Only the relative order matters, so we don't care if the minimum position is now 1.
$position = (int) $project?->pinnedTestMeasurements()->max('position') + 1;
foreach ($newOrder as $id) {
/** @var PinnedTestMeasurement $measurement */
$measurement = $project?->pinnedTestMeasurements()->findOrFail((int) $id);

$measurement->position = $position;
$measurement->save();
$position++;
}

$this->pinnedTestMeasurements = $project?->pinnedTestMeasurements()->orderBy('position')->get();
}
}
2 changes: 1 addition & 1 deletion app/Http/Controllers/BuildController.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function tests(int $build_id): View
'project-name' => $eloquent_project->name,
'build-time' => Carbon::parse($this->build->StartTime)->toIso8601String(),
'initial-filters' => $filters,
'pinned-measurements' => $eloquent_project->measurements()->orderBy('position')->pluck('name')->toArray(),
'pinned-measurements' => $eloquent_project->pinnedTestMeasurements()->orderBy('position')->pluck('name')->toArray(),
]);
}

Expand Down
10 changes: 5 additions & 5 deletions app/Http/Controllers/ManageMeasurementsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace App\Http\Controllers;

use App\Models\Measurement;
use App\Models\PinnedTestMeasurement;
use App\Models\Project as EloquentProject;
use App\Utils\PageTimer;
use Illuminate\Http\JsonResponse;
Expand Down Expand Up @@ -40,7 +40,7 @@ public function apiGet(): JsonResponse
// Get any measurements associated with this project's tests.
$measurements_response = [];
$measurements = EloquentProject::findOrFail($this->project->Id)
->measurements()
->pinnedTestMeasurements()
->orderBy('position', 'asc')
->get();

Expand Down Expand Up @@ -71,9 +71,9 @@ public function apiPost(): JsonResponse
$id = (int) $measurement_data['id'];
if ($id > 0) {
// Update an existing measurement rather than creating a new one.
$measurement = Measurement::find($id);
$measurement = PinnedTestMeasurement::find($id);
} else {
$measurement = new Measurement();
$measurement = new PinnedTestMeasurement();
}
$measurement->projectid = $this->project->Id;
$measurement->name = $measurement_data['name'];
Expand Down Expand Up @@ -107,7 +107,7 @@ public function apiDelete(): JsonResponse
}

$deleted = EloquentProject::findOrFail($this->project->Id)
->measurements()
->pinnedTestMeasurements()
->where('id', (int) request()->input('id'))
->delete();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
* @property string $name
* @property int $position
*
* @mixin Builder<Measurement>
* @mixin Builder<PinnedTestMeasurement>
*/
class Measurement extends Model
class PinnedTestMeasurement extends Model
{
protected $table = 'measurement';

Expand All @@ -37,6 +37,6 @@ class Measurement extends Model
*/
public function project(): BelongsTo
{
return $this->belongsTo(Project::class, 'id', 'projectid');
return $this->belongsTo(Project::class, 'projectid');
}
}
6 changes: 3 additions & 3 deletions app/Models/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,11 @@ public function subprojects(?Carbon $date = null): HasMany
}

/**
* @return HasMany<Measurement, $this>
* @return HasMany<PinnedTestMeasurement, $this>
*/
public function measurements(): HasMany
public function pinnedTestMeasurements(): HasMany
{
return $this->hasMany(Measurement::class, 'projectid', 'id');
return $this->hasMany(PinnedTestMeasurement::class, 'projectid', 'id');
}

/**
Expand Down
15 changes: 15 additions & 0 deletions app/Policies/ProjectPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ public function leave(User $currentUser, Project $project): bool
return !$this->isLdapControlledMembership($project) && $project->users()->where('id', $currentUser->id)->exists();
}

public function createPinnedTestMeasurement(User $currentUser, Project $project): bool
{
return $this->update($currentUser, $project);
}

public function deletePinnedTestMeasurement(User $currentUser, Project $project): bool
{
return $this->update($currentUser, $project);
}

public function updatePinnedTestMeasurementOrder(User $currentUser, Project $project): bool
{
return $this->update($currentUser, $project);
}

private function isLdapControlledMembership(Project $project): bool
{
// If a LDAP filter has been specified and LDAP is enabled, CDash controls the entire members list.
Expand Down
6 changes: 3 additions & 3 deletions app/cdash/app/Controller/Api/QueryTests.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace CDash\Controller\Api;

use App\Models\Measurement;
use App\Models\PinnedTestMeasurement;
use App\Models\Project as EloquentProject;
use App\Models\TestMeasurement;
use CDash\Database;
Expand Down Expand Up @@ -276,10 +276,10 @@ public function getResponse(): array
// Get the list of extra test measurements that should be displayed on this page.
$this->extraMeasurements = [];
$measurements = EloquentProject::findOrFail($this->project->Id)
->measurements()
->pinnedTestMeasurements()
->orderBy('position')
->get();
/** @var Measurement $measurement */
/** @var PinnedTestMeasurement $measurement */
foreach ($measurements as $measurement) {
// If we have the Processors measurement, then we should also
// compute and display 'Proc Time'.
Expand Down
2 changes: 1 addition & 1 deletion app/cdash/app/Controller/Api/TestDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ function () use ($query): void {

// Get the list of extra test measurements that have been explicitly added to this project.
$extra_measurements = EloquentProject::findOrFail($this->project->Id)
->measurements()
->pinnedTestMeasurements()
->orderBy('position')
->pluck('name')
->toArray();
Expand Down
2 changes: 1 addition & 1 deletion app/cdash/app/Controller/Api/ViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public function getResponse()
$response['hasprocessors'] = false;
$processors_idx = -1;
$extra_measurements = EloquentProject::findOrFail($this->project->Id)
->measurements()
->pinnedTestMeasurements()
->orderBy('position')
->get();
foreach ($extra_measurements as $extra_measurement) {
Expand Down
2 changes: 1 addition & 1 deletion app/cdash/public/api/v1/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@
// This is only shown if this project is setup to display
// an extra test measurement called 'Processors'.
$response['showProcTime'] = EloquentProject::findOrFail($Project->Id)
->measurements()
->pinnedTestMeasurements()
->where('name', 'Processors')
->exists();

Expand Down
8 changes: 8 additions & 0 deletions app/cdash/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ add_feature_test_in_transaction(/Feature/GraphQL/UpdateTypeTest)

add_feature_test_in_transaction(/Feature/GraphQL/UpdateFileTypeTest)

add_feature_test_in_transaction(/Feature/GraphQL/PinnedTestMeasurementTypeTest)

add_feature_test_in_transaction(/Feature/RouteAccessTest)

add_feature_test_in_transaction(/Feature/Monitor)
Expand Down Expand Up @@ -274,6 +276,12 @@ add_feature_test_in_transaction(/Feature/GraphQL/Mutations/CreateGlobalInvitatio

add_feature_test_in_transaction(/Feature/GraphQL/Mutations/RevokeGlobalInvitationTest)

add_feature_test_in_transaction(/Feature/GraphQL/Mutations/CreatePinnedTestMeasurementTest)

add_feature_test_in_transaction(/Feature/GraphQL/Mutations/DeletePinnedTestMeasurementTest)

add_feature_test_in_transaction(/Feature/GraphQL/Mutations/UpdatePinnedTestMeasurementOrderTest)

add_feature_test_in_transaction(/Feature/GlobalInvitationAcceptanceTest)

add_feature_test_in_transaction(/Feature/GraphQL/GlobalInvitationTypeTest)
Expand Down
4 changes: 2 additions & 2 deletions app/cdash/tests/test_managemeasurements.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

require_once __DIR__ . '/cdash_test_case.php';

use App\Models\Measurement;
use App\Models\PinnedTestMeasurement;
use App\Utils\DatabaseCleanupUtils;
use CDash\Database;
use GuzzleHttp\Exception\ClientException;
Expand Down Expand Up @@ -41,7 +41,7 @@ public function __destruct()
DatabaseCleanupUtils::removeBuild($this->SubProjectBuildId);
}

Measurement::destroy($this->MeasurementIds);
PinnedTestMeasurement::destroy($this->MeasurementIds);
}

// function to validate test results returned by the API.
Expand Down
Loading