From 9038f1725e46d9b0d401005351992e04a10c45a0 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann Date: Wed, 25 Feb 2026 09:06:10 +0100 Subject: [PATCH 1/4] Add permanent removal and restore functionality for projects Permanent project removal and restore was added to Gitlab Free in 18.0. --- src/Api/Projects.php | 16 ++++++++++++++-- tests/Api/ProjectsTest.php | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index 32aa168a..72a91acc 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -194,9 +194,21 @@ public function update(int|string $project_id, array $parameters): mixed return $this->put('projects/'.self::encodePath($project_id), $parameters); } - public function remove(int|string $project_id): mixed + public function remove(int|string $project_id, bool $permanent = false, string $fullPath = ""): mixed + { + $params = []; + if ($permanent) { + $params = [ + 'permanently_remove' => true, + 'full_path' => $fullPath + ]; + } + return $this->delete('projects/'.self::encodePath($project_id), $params); + } + + public function restore(int|string $project_id): mixed { - return $this->delete('projects/'.self::encodePath($project_id)); + return $this->post('projects/'.self::encodePath($project_id).'/restore'); } public function archive(int|string $project_id): mixed diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index 62b5dfcc..7a1e185f 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -345,6 +345,35 @@ public function shouldRemoveProject(): void $this->assertEquals($expectedBool, $api->remove(1)); } + #[Test] + public function shouldRemoveProjectPermanently(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('delete') + ->with('projects/1', ['permanently_remove' => true, 'full_path' => 'full/path/to/project']) + ->willReturn(true); + + $this->assertEquals($expectedBool, $api->remove(1, true, 'full/path/to/project')); + + } + + #[Test] + public function shouldRestoreDeletedProject(): void + { + $expectedBool = true; + + $api = $this->getApiMock(); + $api->expects($this->once()) + ->method('post') + ->with('projects/1/restore') + ->willReturn(true); + + $this->assertEquals($expectedBool, $api->restore(1)); + } + #[Test] public function shouldGetPipelines(): void { From 3d788209ab4176bacd9d761cce11973a90171dad Mon Sep 17 00:00:00 2001 From: Philipp Kolmann Date: Wed, 25 Feb 2026 09:09:07 +0100 Subject: [PATCH 2/4] Fix formatting in remove method and project removal test --- src/Api/Projects.php | 4 ++-- tests/Api/ProjectsTest.php | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index 72a91acc..cdcb6cfc 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -194,13 +194,13 @@ public function update(int|string $project_id, array $parameters): mixed return $this->put('projects/'.self::encodePath($project_id), $parameters); } - public function remove(int|string $project_id, bool $permanent = false, string $fullPath = ""): mixed + public function remove(int|string $project_id, bool $permanent = false, string $fullPath = ''): mixed { $params = []; if ($permanent) { $params = [ 'permanently_remove' => true, - 'full_path' => $fullPath + 'full_path' => $fullPath, ]; } return $this->delete('projects/'.self::encodePath($project_id), $params); diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index 7a1e185f..b90b4608 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -357,7 +357,6 @@ public function shouldRemoveProjectPermanently(): void ->willReturn(true); $this->assertEquals($expectedBool, $api->remove(1, true, 'full/path/to/project')); - } #[Test] From 0de51e9e7598cdb111ff0ba754f3add9279c656e Mon Sep 17 00:00:00 2001 From: Philipp Kolmann Date: Wed, 25 Feb 2026 09:10:13 +0100 Subject: [PATCH 3/4] Fix formatting in Projects.php for delete method --- src/Api/Projects.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index cdcb6cfc..f1830e88 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -203,6 +203,7 @@ public function remove(int|string $project_id, bool $permanent = false, string $ 'full_path' => $fullPath, ]; } + return $this->delete('projects/'.self::encodePath($project_id), $params); } From f1d4d4194eea20b65919319055d3f8f0cf74e681 Mon Sep 17 00:00:00 2001 From: Philipp Kolmann Date: Wed, 25 Feb 2026 09:15:15 +0100 Subject: [PATCH 4/4] Refactor remove method to accept parameters as an array in Projects.php --- src/Api/Projects.php | 14 +++----------- tests/Api/ProjectsTest.php | 5 ++++- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/Api/Projects.php b/src/Api/Projects.php index f1830e88..a2d0a7a3 100644 --- a/src/Api/Projects.php +++ b/src/Api/Projects.php @@ -194,17 +194,9 @@ public function update(int|string $project_id, array $parameters): mixed return $this->put('projects/'.self::encodePath($project_id), $parameters); } - public function remove(int|string $project_id, bool $permanent = false, string $fullPath = ''): mixed - { - $params = []; - if ($permanent) { - $params = [ - 'permanently_remove' => true, - 'full_path' => $fullPath, - ]; - } - - return $this->delete('projects/'.self::encodePath($project_id), $params); + public function remove(int|string $project_id, array $parameters = []): mixed + { + return $this->delete('projects/'.self::encodePath($project_id), $parameters); } public function restore(int|string $project_id): mixed diff --git a/tests/Api/ProjectsTest.php b/tests/Api/ProjectsTest.php index b90b4608..fb108a2f 100644 --- a/tests/Api/ProjectsTest.php +++ b/tests/Api/ProjectsTest.php @@ -356,7 +356,10 @@ public function shouldRemoveProjectPermanently(): void ->with('projects/1', ['permanently_remove' => true, 'full_path' => 'full/path/to/project']) ->willReturn(true); - $this->assertEquals($expectedBool, $api->remove(1, true, 'full/path/to/project')); + $this->assertEquals($expectedBool, $api->remove(1, [ + 'permanently_remove' => true, + 'full_path' => 'full/path/to/project', + ])); } #[Test]