Files
KanbanGit/app/Http/Controllers/ProjectTicketBranchController.php
T
Eric Peters 1c355c20b4
linter / quality (pull_request) Successful in 1m13s
tests / ci (8.4) (pull_request) Failing after 1m15s
DEleted function in request and changed the way the controller uses it,
2026-04-03 16:50:00 +02:00

218 lines
7.2 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Actions\Git\Data\GitBranch;
use App\Actions\Git\GitProviderManager;
use App\Actions\Git\ValidateGitBranchName;
use App\Actions\ProjectPermissions\ProjectPermissionService;
use App\Http\Requests\StoreProjectTicketBranchRequest;
use App\Http\Requests\ValidateProjectTicketBranchRequest;
use App\Models\Project;
use App\Models\RepositoryConnection;
use App\Models\Ticket;
use App\Models\UserGitConnection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Arr;
use Illuminate\Validation\ValidationException;
use Throwable;
class ProjectTicketBranchController extends Controller
{
public function __construct(
private readonly GitProviderManager $gitProviderManager,
private readonly ValidateGitBranchName $validateGitBranchName,
private readonly ProjectPermissionService $projectPermissionService,
) {}
public function validate(
ValidateProjectTicketBranchRequest $request,
Project $project,
Ticket $ticket,
): JsonResponse {
$user = $request->user();
abort_unless(
$this->projectPermissionService->userHasPermission($user, $project, 'edit'),
403,
);
$validated = $request->validated();
$repositoryConnectionId = Arr::get($validated, 'repository_connection_id');
$branchName = trim((string) Arr::get($validated, 'branch_name'));
$repositoryConnection = $this->projectRepositoryConnection(
$project,
$repositoryConnectionId,
);
$userGitConnection = $this->matchingUserGitConnection(
$user->id,
$repositoryConnection,
);
if ($userGitConnection === null) {
return response()->json([
'is_valid' => false,
'message' => 'Connect a matching Git connection in your user settings first.',
]);
}
$syntaxMessage = $this->validateGitBranchName->message($branchName);
if ($syntaxMessage !== null) {
return response()->json([
'is_valid' => false,
'message' => $syntaxMessage,
]);
}
try {
$branchAlreadyExists = collect(
$this->gitProviderManager
->client($userGitConnection->provider)
->listBranches(
$userGitConnection->base_url,
$userGitConnection->api_token,
$repositoryConnection->owner_name,
$repositoryConnection->repository_name,
),
)
->contains(
fn (GitBranch $branch): bool => $branch->name === $branchName,
);
} catch (Throwable) {
return response()->json([
'is_valid' => false,
'message' => 'KanbanGit could not validate this branch name right now.',
]);
}
if ($branchAlreadyExists) {
return response()->json([
'is_valid' => false,
'message' => 'This branch name already exists in the selected repository.',
]);
}
return response()->json([
'is_valid' => true,
'message' => "Branch name is available for {$ticket->ticket_key}.",
]);
}
public function store(
StoreProjectTicketBranchRequest $request,
Project $project,
Ticket $ticket,
): RedirectResponse {
$user = $request->user();
abort_unless(
$this->projectPermissionService->userHasPermission($user, $project, 'edit'),
403,
);
$validated = $request->validated();
$repositoryConnectionId = Arr::get($validated, 'repository_connection_id');
$branchName = trim((string) Arr::get($validated, 'branch_name'));
$repositoryConnection = $this->projectRepositoryConnection(
$project,
$repositoryConnectionId,
);
$userGitConnection = $this->matchingUserGitConnection(
$user->id,
$repositoryConnection,
);
if ($userGitConnection === null) {
throw ValidationException::withMessages([
'repository_connection_id' => 'Connect a matching Git connection in your user settings first.',
]);
}
$syntaxMessage = $this->validateGitBranchName->message($branchName);
if ($syntaxMessage !== null) {
throw ValidationException::withMessages([
'branch_name' => $syntaxMessage,
]);
}
$gitProvider = $this->gitProviderManager->client($userGitConnection->provider);
try {
$branchAlreadyExists = collect(
$gitProvider->listBranches(
$userGitConnection->base_url,
$userGitConnection->api_token,
$repositoryConnection->owner_name,
$repositoryConnection->repository_name,
),
)
->contains(
fn (GitBranch $branch): bool => $branch->name === $branchName,
);
} catch (Throwable) {
throw ValidationException::withMessages([
'branch_name' => 'KanbanGit could not validate this branch name right now.',
]);
}
if ($branchAlreadyExists) {
throw ValidationException::withMessages([
'branch_name' => 'This branch name already exists in the selected repository.',
]);
}
try {
$repository = $gitProvider->getRepository(
$userGitConnection->base_url,
$userGitConnection->api_token,
$repositoryConnection->owner_name,
$repositoryConnection->repository_name,
);
$gitProvider->createBranch(
$userGitConnection->base_url,
$userGitConnection->api_token,
$repositoryConnection->owner_name,
$repositoryConnection->repository_name,
$branchName,
$repository->defaultBranch,
);
} catch (Throwable) {
throw ValidationException::withMessages([
'branch_name' => 'KanbanGit could not create this branch right now.',
]);
}
return to_route('projects.tickets.show', [$project, $ticket])
->with(
'status',
"{$branchName} was created in {$repositoryConnection->repository_full_name}.",
);
}
private function projectRepositoryConnection(Project $project, int $repositoryConnectionId): RepositoryConnection
{
return $project->repositoryConnections()
->findOrFail($repositoryConnectionId);
}
private function matchingUserGitConnection(
int $userId,
RepositoryConnection $repositoryConnection,
): ?UserGitConnection {
return UserGitConnection::query()
->where('user_id', $userId)
->where('provider', $repositoryConnection->provider)
->where('base_url', $repositoryConnection->base_url)
->first();
}
}