From 6c4710901c961a76a58c9252a0423890aaf3208c Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 6 Mar 2024 08:18:57 +0100 Subject: [PATCH 1/8] chore(test): add php 8.3 to test matrix and fix sample repo for private gitea instance (refs #25) --- .github/workflows/ci.yml | 2 +- README.md | 2 +- composer.json | 3 ++- tests/GogsClientTest.php | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf5206f..1feb999 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - php-version: [7.4,8.1,8.2] + php-version: [8.1,8.2] runs-on: ubuntu-latest diff --git a/README.md b/README.md index 1ce208d..3435cc0 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ This module is also used by [mborne/git-manager](https://github.com/mborne/git-m ## Requirements -* PHP >= 7.4 or >= 8.x +* [PHP >= 8.1](https://www.php.net/supported-versions.php) ## Supported GIT hosting services diff --git a/composer.json b/composer.json index 8e79247..1c7ce97 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,7 @@ "friendsofphp/php-cs-fixer": "3.17.*", "phpmd/phpmd": "^2.8", "pdepend/pdepend": "2.15.*", - "php-coveralls/php-coveralls": "^2.5" + "php-coveralls/php-coveralls": "^2.5", + "phpstan/phpstan": "^1.10" } } diff --git a/tests/GogsClientTest.php b/tests/GogsClientTest.php index cc0995a..4cf99e6 100644 --- a/tests/GogsClientTest.php +++ b/tests/GogsClientTest.php @@ -61,10 +61,10 @@ public function testFindByCurrentUser() } $this->assertArrayHasKey( - 'docker/docker-php', + 'docker/docker-php-sury', $projectsByName ); - $project = $projectsByName['docker/docker-php']; + $project = $projectsByName['docker/docker-php-sury']; $this->assertStringContainsString( 'FROM ', $client->getRawFile($project, 'Dockerfile', 'master') @@ -101,10 +101,10 @@ public function testFindByUserAndOrgs() } $this->assertArrayHasKey( - 'docker/docker-php', + 'docker/docker-php-sury', $projectsByName ); - $project = $projectsByName['docker/docker-php']; + $project = $projectsByName['docker/docker-php-sury']; $this->assertStringContainsString( 'FROM ', $client->getRawFile($project, 'Dockerfile', 'master') From 35ad3d187bc4f567b1067902491d8ed89b5b5951 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 6 Mar 2024 08:26:19 +0100 Subject: [PATCH 2/8] chore(phpstan): add phpstan and fixe level 1 issues (refs #25) --- Makefile | 6 +++++- phpstan.neon | 5 +++++ src/Filter/RequiredFileFilter.php | 5 +++++ src/Gitlab/GitlabClient.php | 2 +- src/Local/LocalClient.php | 2 -- tests/GitlabClientTest.php | 1 + 6 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 phpstan.neon diff --git a/Makefile b/Makefile index 8ecd063..bb45e55 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,14 @@ test: check-style check-rules --coverage-html output/coverage .PHONY: check-rules -check-rules: vendor +check-rules: phpstan phpmd + +phpmd: @echo "-- Checking coding rules using phpmd (see @SuppressWarning to bypass control)" vendor/bin/phpmd src text $(PHP_MD_RULES) +phpstan: + vendor/bin/phpstan analyse -c phpstan.neon --error-format=raw .PHONY: fix-style fix-style: vendor diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..c8b9993 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,5 @@ +parameters: + level: 1 + paths: + - src + - tests diff --git a/src/Filter/RequiredFileFilter.php b/src/Filter/RequiredFileFilter.php index aee2958..1f766ac 100644 --- a/src/Filter/RequiredFileFilter.php +++ b/src/Filter/RequiredFileFilter.php @@ -25,6 +25,11 @@ class RequiredFileFilter implements ProjectFilterInterface */ protected $filePath; + /** + * @var LoggerInterface + */ + protected $logger; + /** * @param string $filePath * @param LoggerInterface $logger diff --git a/src/Gitlab/GitlabClient.php b/src/Gitlab/GitlabClient.php index a852794..07ad195 100644 --- a/src/Gitlab/GitlabClient.php +++ b/src/Gitlab/GitlabClient.php @@ -138,7 +138,7 @@ protected function findBySearch(FindOptions $options) */ private function fetchAllPages( $path, - array $params = [], + array $params, ProjectFilterInterface $projectFilter ) { $result = []; diff --git a/src/Local/LocalClient.php b/src/Local/LocalClient.php index aa92d66..0880605 100644 --- a/src/Local/LocalClient.php +++ b/src/Local/LocalClient.php @@ -99,8 +99,6 @@ public function createLocalProject($projectFolder) * * @param string $parentPath absolute path to a given folder * - * @return string[] - * * @SuppressWarnings(PHPMD.ElseExpression) */ protected function findProjectFolders($parentPath, array &$projectFolders) diff --git a/tests/GitlabClientTest.php b/tests/GitlabClientTest.php index e1b10c5..e420f4f 100644 --- a/tests/GitlabClientTest.php +++ b/tests/GitlabClientTest.php @@ -78,6 +78,7 @@ public function testGitlabDotComOrgs() $findOptions = new FindOptions(); $findOptions->setOrganizations(['gitlab-org']); $projects = $client->find($findOptions); + $projectsByName = []; foreach ($projects as $project) { $this->assertInstanceOf(GitlabProject::class, $project); $this->assertGettersWorks($project); From 8303b8913b88f9347f11a093c0ba7c0996f96d92 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 6 Mar 2024 08:31:05 +0100 Subject: [PATCH 3/8] chore(phpstan): fix level 2 issues (refs #25) --- phpstan.neon | 2 +- src/ClientInterface.php | 6 +++--- src/Filter/ComposerProjectFilter.php | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index c8b9993..da11cce 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 1 + level: 2 paths: - src - tests diff --git a/src/ClientInterface.php b/src/ClientInterface.php index be7e9ef..f06729f 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -20,9 +20,9 @@ public function find(FindOptions $options); /** * Get raw file * - * @param string $projectId ex : 123456 - * @param string $filePath ex : composer.json - * @param string $ref ex : master + * @param ProjectInterface $project ex : 123456 + * @param string $filePath ex : composer.json + * @param string $ref ex : master * * @return string */ diff --git a/src/Filter/ComposerProjectFilter.php b/src/Filter/ComposerProjectFilter.php index a96f359..96f60a3 100644 --- a/src/Filter/ComposerProjectFilter.php +++ b/src/Filter/ComposerProjectFilter.php @@ -37,7 +37,6 @@ class ComposerProjectFilter implements ProjectFilterInterface /** * ProjectTypeFilter constructor. * - * @param string $type * @param LoggerInterface $logger * * @SuppressWarnings(PHPMD.StaticAccess) From a1b22a1072753edbdad03dadab95254dd8f31122 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 6 Mar 2024 08:51:50 +0100 Subject: [PATCH 4/8] chore(phpstan): fix level 3 issues and add types to tests (refs #25) --- phpstan.neon | 2 +- src/ProjectInterface.php | 2 +- tests/ClientFactoryTest.php | 6 +++--- tests/Filter/ComposerProjectFilterTest.php | 12 ++++++++---- tests/Filter/FilterCollectionTest.php | 14 ++++++-------- tests/Filter/IgnoreRegexpFilterTest.php | 2 +- tests/Filter/RequiredFileFilterTest.php | 4 +++- tests/GithubClientTest.php | 15 +++++++++------ tests/GitlabClientTest.php | 15 +++++++++------ tests/GogsClientTest.php | 14 ++++++++------ tests/Http/TokenTypeTest.php | 2 +- tests/LocalClientTest.php | 17 +++++++++-------- tests/TestCase.php | 6 ++---- 13 files changed, 61 insertions(+), 50 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index da11cce..7ee3062 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 2 + level: 3 paths: - src - tests diff --git a/src/ProjectInterface.php b/src/ProjectInterface.php index a526d9a..2b28069 100644 --- a/src/ProjectInterface.php +++ b/src/ProjectInterface.php @@ -26,7 +26,7 @@ public function getName(); /** * Get default branch * - * @return string + * @return ?string */ public function getDefaultBranch(); diff --git a/tests/ClientFactoryTest.php b/tests/ClientFactoryTest.php index 71dbd20..0cd2acd 100644 --- a/tests/ClientFactoryTest.php +++ b/tests/ClientFactoryTest.php @@ -11,7 +11,7 @@ class ClientFactoryTest extends TestCase { - public function testGetTypes() + public function testGetTypes(): void { $clientFactory = ClientFactory::getInstance(); @@ -19,7 +19,7 @@ public function testGetTypes() $this->assertCount(4, $types); } - public function testInvalidType() + public function testInvalidType(): void { $clientFactory = ClientFactory::getInstance(); $thrown = false; @@ -33,7 +33,7 @@ public function testInvalidType() $this->assertTrue($thrown, 'exception should be thrown'); } - public function testDetectClientType() + public function testDetectClientType(): void { $this->assertEquals( GithubClient::class, diff --git a/tests/Filter/ComposerProjectFilterTest.php b/tests/Filter/ComposerProjectFilterTest.php index 6f663a7..35cdf87 100644 --- a/tests/Filter/ComposerProjectFilterTest.php +++ b/tests/Filter/ComposerProjectFilterTest.php @@ -14,11 +14,12 @@ class ComposerProjectFilterTest extends TestCase /** * Test getDescription */ - public function testGetDescription() + public function testGetDescription(): void { $gitClient = $this->getMockBuilder(ClientInterface::class) ->getMock() ; + /** @var ClientInterface $gitClient */ $filter = new ComposerProjectFilter($gitClient); $this->assertEquals( 'composer.json should exists', @@ -34,7 +35,7 @@ public function testGetDescription() /** * Rejected if composer.json doesn't exists */ - public function testMissingComposerJson() + public function testMissingComposerJson(): void { $project = $this->createMockProject('test'); @@ -46,6 +47,7 @@ public function testMissingComposerJson() ->method('getRawFile') ->willThrowException(new \Exception('404 not found')) ; + /** @var ClientInterface $gitClient */ $filter = new ComposerProjectFilter($gitClient); $this->assertFalse($filter->isAccepted($project)); } @@ -53,7 +55,7 @@ public function testMissingComposerJson() /** * Accepted if composer.json exists */ - public function testComposerJsonAndTypeFilter() + public function testComposerJsonAndTypeFilter(): void { $project = $this->createMockProject('test'); @@ -70,6 +72,7 @@ public function testComposerJsonAndTypeFilter() // ->with(['composer.json']) ->willReturn(json_encode($content)) ; + /** @var ClientInterface $gitClient */ $filter = new ComposerProjectFilter($gitClient); $this->assertTrue($filter->isAccepted($project)); @@ -85,7 +88,7 @@ public function testComposerJsonAndTypeFilter() /** * Accepted if composer.json exists */ - public function testComposerJsonAndMultipleTypeFilter() + public function testComposerJsonAndMultipleTypeFilter(): void { $project = $this->createMockProject('test'); @@ -102,6 +105,7 @@ public function testComposerJsonAndMultipleTypeFilter() // ->with(['composer.json']) ->willReturn(json_encode($content)) ; + /** @var ClientInterface $gitClient */ $filter = new ComposerProjectFilter($gitClient); $this->assertTrue($filter->isAccepted($project)); $filter->setProjectType('project,library'); diff --git a/tests/Filter/FilterCollectionTest.php b/tests/Filter/FilterCollectionTest.php index 19e107d..efa08f6 100644 --- a/tests/Filter/FilterCollectionTest.php +++ b/tests/Filter/FilterCollectionTest.php @@ -12,7 +12,7 @@ */ class FilterCollectionTest extends TestCase { - public function testEmpty() + public function testEmpty(): void { $filterCollection = new FilterCollection(new NullLogger()); $project = $this->createMockProject('test'); @@ -20,13 +20,11 @@ public function testEmpty() } /** - * Create a fake project filter returning true or false - * - * @param bool $accepted + * Create a fake ProjectFilterInterface returning true or false * * @return ProjectFilterInterface */ - private function createMockFilter($accepted, $description = 'mock') + private function createMockFilter(bool $accepted, string $description = 'mock') { $filter = $this->getMockBuilder(ProjectFilterInterface::class) ->getMock() @@ -43,7 +41,7 @@ private function createMockFilter($accepted, $description = 'mock') return $filter; } - public function testOneTrue() + public function testOneTrue(): void { $filterCollection = new FilterCollection(new NullLogger()); $filterCollection->addFilter($this->createMockFilter(true)); @@ -51,7 +49,7 @@ public function testOneTrue() $this->assertTrue($filterCollection->isAccepted($project)); } - public function testOneFalse() + public function testOneFalse(): void { $filterCollection = new FilterCollection(new NullLogger()); $filterCollection->addFilter($this->createMockFilter(false)); @@ -62,7 +60,7 @@ public function testOneFalse() /** * Check that isAccepted is unanymous */ - public function testTrueFalseTrue() + public function testTrueFalseTrue(): void { $filterCollection = new FilterCollection(new NullLogger()); $filterCollection->addFilter($this->createMockFilter(true, 'mock-1')); diff --git a/tests/Filter/IgnoreRegexpFilterTest.php b/tests/Filter/IgnoreRegexpFilterTest.php index ad79804..a6cb4ed 100644 --- a/tests/Filter/IgnoreRegexpFilterTest.php +++ b/tests/Filter/IgnoreRegexpFilterTest.php @@ -10,7 +10,7 @@ */ class IgnoreRegexpFilterTest extends TestCase { - public function testExample() + public function testExample(): void { $filter = new IgnoreRegexpFilter('(^phpstorm|^typo3\/library)'); diff --git a/tests/Filter/RequiredFileFilterTest.php b/tests/Filter/RequiredFileFilterTest.php index 640857f..ad4fb1e 100644 --- a/tests/Filter/RequiredFileFilterTest.php +++ b/tests/Filter/RequiredFileFilterTest.php @@ -14,7 +14,7 @@ class RequiredFileFilterTest extends TestCase /** * Rejected if composer.json doesn't exists */ - public function testRequiredFileMissing() + public function testRequiredFileMissing(): void { $project = $this->createMockProject('test'); @@ -26,6 +26,7 @@ public function testRequiredFileMissing() ->method('getRawFile') ->willThrowException(new \Exception('404 not found')) ; + /** @var ClientInterface $gitClient */ $filter = new RequiredFileFilter($gitClient, 'README.md'); $this->assertFalse($filter->isAccepted($project)); } @@ -47,6 +48,7 @@ public function testRequiredFilePresent() // ->with(['composer.json']) ->willReturn(json_encode($content)) ; + /** @var ClientInterface $gitClient */ $filter = new RequiredFileFilter($gitClient, 'README.md'); $this->assertTrue($filter->isAccepted($project)); } diff --git a/tests/GithubClientTest.php b/tests/GithubClientTest.php index 820f03c..a24aa5c 100644 --- a/tests/GithubClientTest.php +++ b/tests/GithubClientTest.php @@ -12,9 +12,9 @@ class GithubClientTest extends TestCase { /** - * @return GithubClient + * Create GithubClient using GITHUB_TOKEN. */ - protected function createGithubClient() + protected function createGithubClient(): GithubClient { $token = getenv('GITHUB_TOKEN'); if (empty($token)) { @@ -28,16 +28,19 @@ protected function createGithubClient() ; /* create client */ - return ClientFactory::createClient( + $client = ClientFactory::createClient( $clientOptions, new NullLogger() ); + $this->assertInstanceOf(GithubClient::class, $client); + + return $client; } /** * Ensure client can find mborne's projects */ - public function testUserAndOrgsRepositories() + public function testUserAndOrgsRepositories(): void { /* create client */ $client = $this->createGithubClient(); @@ -84,7 +87,7 @@ public function testUserAndOrgsRepositories() /** * Ensure client can find mborne's projects with composer.json file */ - public function testFilterFile() + public function testFilterFile(): void { /* create client */ $client = $this->createGithubClient(); @@ -125,7 +128,7 @@ public function testFilterFile() /** * Ensure client can find mborne's projects using _me_ */ - public function testFakeUserMe() + public function testFakeUserMe(): void { $ci = getenv('CI'); if (!empty($ci)) { diff --git a/tests/GitlabClientTest.php b/tests/GitlabClientTest.php index e420f4f..ec091d9 100644 --- a/tests/GitlabClientTest.php +++ b/tests/GitlabClientTest.php @@ -12,9 +12,9 @@ class GitlabClientTest extends TestCase { /** - * @return GitlabClient + * Create GitlabClient using GITLAB_TOKEN. */ - protected function createGitlabClient() + protected function createGitlabClient(): GitlabClient { $gitlabToken = getenv('GITLAB_TOKEN'); if (empty($gitlabToken)) { @@ -28,16 +28,19 @@ protected function createGitlabClient() ; /* create client */ - return ClientFactory::createClient( + $client = ClientFactory::createClient( $clientOptions, new NullLogger() ); + $this->assertInstanceOf(GitlabClient::class, $client); + + return $client; } /** * Ensure client can find mborne/sample-composer by username */ - public function testGitlabDotComByUser() + public function testGitlabDotComByUser(): void { /* create client */ $client = $this->createGitlabClient(); @@ -68,7 +71,7 @@ public function testGitlabDotComByUser() $this->assertStringContainsString('mborne@users.noreply.github.com', $composer); } - public function testGitlabDotComOrgs() + public function testGitlabDotComOrgs(): void { /* create client */ $client = $this->createGitlabClient(); @@ -93,7 +96,7 @@ public function testGitlabDotComOrgs() /** * Ensure client can find mborne/sample-composer with search */ - public function testGitlabDotComSearch() + public function testGitlabDotComSearch(): void { /* create client */ $client = $this->createGitlabClient(); diff --git a/tests/GogsClientTest.php b/tests/GogsClientTest.php index 4cf99e6..e8d6819 100644 --- a/tests/GogsClientTest.php +++ b/tests/GogsClientTest.php @@ -5,7 +5,6 @@ use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\ClientFactory; use MBO\RemoteGit\FindOptions; -use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Gogs\GogsClient; use MBO\RemoteGit\Gogs\GogsProject; @@ -15,9 +14,9 @@ class GogsClientTest extends TestCase { /** - * @return ClientInterface + * Create gogs client for codes.quadtreeworld.net using QTW_TOKEN. */ - protected function createGitClient() + protected function createGitClient(): GogsClient { $gitlabToken = getenv('QTW_TOKEN'); if (empty($gitlabToken)) { @@ -32,15 +31,18 @@ protected function createGitClient() ; /* create client */ - return ClientFactory::createClient( + $client = ClientFactory::createClient( $clientOptions ); + $this->assertInstanceOf(GogsClient::class, $client); + + return $client; } /** * Test find by current user */ - public function testFindByCurrentUser() + public function testFindByCurrentUser(): void { /* create client */ $client = $this->createGitClient(); @@ -78,7 +80,7 @@ public function testFindByCurrentUser() /** * Ensure client can find projects by username and organizations */ - public function testFindByUserAndOrgs() + public function testFindByUserAndOrgs(): void { /* create client */ $client = $this->createGitClient(); diff --git a/tests/Http/TokenTypeTest.php b/tests/Http/TokenTypeTest.php index 18892d8..6ff25a4 100644 --- a/tests/Http/TokenTypeTest.php +++ b/tests/Http/TokenTypeTest.php @@ -7,7 +7,7 @@ class TokenTypeTest extends TestCase { - public function testCreateHttpHeaders() + public function testCreateHttpHeaders(): void { // empty headers for null token $this->assertEquals( diff --git a/tests/LocalClientTest.php b/tests/LocalClientTest.php index 7370de9..84eefb4 100644 --- a/tests/LocalClientTest.php +++ b/tests/LocalClientTest.php @@ -31,10 +31,8 @@ public static function setUpBeforeClass(): void /** * Create a LocalClient for sample test directory - * - * @return LocalClient */ - protected function createLocalClient() + protected function createLocalClient(): LocalClient { // folder containing mborne/remote-git and mborne/satis-gitlab $rootPath = realpath(self::TEMP_DIR); @@ -45,10 +43,13 @@ protected function createLocalClient() ; /* create client */ - return ClientFactory::createClient( + $client = ClientFactory::createClient( $clientOptions, new NullLogger() ); + $this->assertInstanceOf(LocalClient::class, $client); + + return $client; } /** @@ -56,7 +57,7 @@ protected function createLocalClient() * * @return LocalProject[] */ - protected function findAllProjects() + protected function findAllProjects(): array { /* create client */ $client = $this->createLocalClient(); @@ -78,7 +79,7 @@ protected function findAllProjects() /** * Ensure that mborne/remote-git and mborne/satis-gitlab are found */ - public function testFindAll() + public function testFindAll(): void { $projectsByName = $this->findAllProjects(); $this->assertArrayHasKey( @@ -91,7 +92,7 @@ public function testFindAll() /** * Check that raw file content can be retreived from non bare repository */ - public function testGetRawFileFromNonBareRepository() + public function testGetRawFileFromNonBareRepository(): void { $client = $this->createLocalClient(); $project = $client->createLocalProject(self::TEMP_DIR.'/mborne/remote-git'); @@ -105,7 +106,7 @@ public function testGetRawFileFromNonBareRepository() /** * Check that raw file content can be retreived from bare repository */ - public function testGetRawFileFromBareRepository() + public function testGetRawFileFromBareRepository(): void { $client = $this->createLocalClient(); $project = $client->createLocalProject(self::TEMP_DIR.'/mborne/satis-gitlab.git'); diff --git a/tests/TestCase.php b/tests/TestCase.php index a095ea8..d7c05e9 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,11 +10,9 @@ class TestCase extends BaseTestCase /** * Create a fake project with a given name * - * @param string $projectName - * * @return ProjectInterface */ - protected function createMockProject($projectName) + protected function createMockProject(string $projectName) { $project = $this->getMockBuilder(ProjectInterface::class) ->getMock() @@ -34,7 +32,7 @@ protected function createMockProject($projectName) /** * Ensure that getter works for project */ - protected function assertGettersWorks(ProjectInterface $project) + protected function assertGettersWorks(ProjectInterface $project): void { $this->assertNotEmpty($project->getId()); $this->assertNotEmpty($project->getName()); From 9af31533422e256636d84c2b6e094fbf5253d591 Mon Sep 17 00:00:00 2001 From: mborne Date: Mon, 11 Mar 2024 16:11:30 +0100 Subject: [PATCH 5/8] chore(phpstan): fix level 8 issues improving error handling (refs #25) --- phpstan.neon | 2 +- src/AbstractClient.php | 26 ++++---- src/ClientFactory.php | 34 ++++------ src/ClientInterface.php | 10 ++- src/ClientOptions.php | 68 ++++++-------------- src/Exception/ClientNotFoundException.php | 5 +- src/Exception/MissingConstException.php | 2 +- src/Exception/RawFileNotFoundException.php | 21 ++++++ src/Exception/RequiredParameterException.php | 2 +- src/Filter/ComposerProjectFilter.php | 31 +++------ src/Filter/FilterCollection.php | 20 +++--- src/Filter/IgnoreRegexpFilter.php | 12 ++-- src/Filter/RequiredFileFilter.php | 14 ++-- src/FindOptions.php | 48 ++++---------- src/Github/GithubClient.php | 54 +++++++++------- src/Github/GithubProject.php | 38 +++++------ src/Gitlab/GitlabClient.php | 51 ++++++++------- src/Gitlab/GitlabProject.php | 38 +++++------ src/Gogs/GogsClient.php | 48 ++++++++------ src/Gogs/GogsProject.php | 38 +++++------ src/Helper/ClientHelper.php | 4 +- src/Helper/LoggerHelper.php | 6 +- src/Http/TokenType.php | 5 +- src/Local/LocalClient.php | 59 ++++++++++------- src/Local/LocalProject.php | 27 ++++---- src/ProjectFilterInterface.php | 8 +-- src/ProjectInterface.php | 20 ++---- tests/ClientFactoryTest.php | 12 +++- tests/Filter/RequiredFileFilterTest.php | 2 +- tests/GithubClientTest.php | 16 +++-- tests/GitlabClientTest.php | 12 +++- tests/GogsClientTest.php | 5 ++ tests/LocalClientTest.php | 24 ++++--- tests/TestCase.php | 28 ++++++++ 34 files changed, 405 insertions(+), 385 deletions(-) create mode 100644 src/Exception/RawFileNotFoundException.php diff --git a/phpstan.neon b/phpstan.neon index 7ee3062..7f33c04 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,5 @@ parameters: - level: 3 + level: 8 paths: - src - tests diff --git a/src/AbstractClient.php b/src/AbstractClient.php index eb0c571..67478dd 100644 --- a/src/AbstractClient.php +++ b/src/AbstractClient.php @@ -40,7 +40,7 @@ protected function __construct( /** * @return GuzzleHttpClient */ - protected function getHttpClient() + protected function getHttpClient(): GuzzleHttpClient { return $this->httpClient; } @@ -48,7 +48,7 @@ protected function getHttpClient() /** * @return LoggerInterface */ - protected function getLogger() + protected function getLogger(): LoggerInterface { return $this->logger; } @@ -56,19 +56,23 @@ protected function getLogger() /** * Create a project according to JSON metadata provided by an API * + * @param array $rawProject + * * @return ProjectInterface */ - abstract protected function createProject(array $rawProject); + abstract protected function createProject(array $rawProject): ProjectInterface; /** * Get projets for a given path with parameters * + * @param array $params + * * @return ProjectInterface[] */ protected function getProjects( - $path, + string $path, array $params = [] - ) { + ): array { $uri = $path.'?'.$this->implodeParams($params); $this->getLogger()->debug('GET '.$uri); $response = $this->getHttpClient()->request('GET', $uri); @@ -82,17 +86,15 @@ protected function getProjects( } /** - * Implode params to performs request - * - * @param array $params key=>value + * Implode params to performs HTTP request * - * @return string + * @param array $params key=>value */ - protected function implodeParams($params) + protected function implodeParams(array $params): string { $parts = []; foreach ($params as $key => $value) { - $parts[] = $key.'='.urlencode($value); + $parts[] = $key.'='.urlencode((string) $value); } return implode('&', $parts); @@ -105,7 +107,7 @@ protected function implodeParams($params) * * @return ProjectInterface[] */ - protected function filter(array $projects, ProjectFilterInterface $filter) + protected function filter(array $projects, ProjectFilterInterface $filter): array { $result = []; foreach ($projects as $project) { diff --git a/src/ClientFactory.php b/src/ClientFactory.php index b67a272..2fe045c 100644 --- a/src/ClientFactory.php +++ b/src/ClientFactory.php @@ -30,7 +30,7 @@ class ClientFactory /** * Associates client type to metadata ('className','tokenType') * - * @var array + * @var array> */ private $types = []; @@ -66,31 +66,23 @@ public function getTypes() /** * Create a client with options - * - * @param LoggerInterface $logger - * - * @return ClientInterface */ public static function createClient( ClientOptions $options, LoggerInterface $logger = null - ) { + ): ClientInterface { return self::getInstance()->createGitClient($options, $logger); } /** * Create a client with options * - * @param LoggerInterface $logger - * - * @return ClientInterface - * * @SuppressWarnings(PHPMD.StaticAccess) */ public function createGitClient( ClientOptions $options, LoggerInterface $logger = null - ) { + ): ClientInterface { $logger = LoggerHelper::handleNull($logger); /* Detect client type from URL if not specified */ @@ -141,17 +133,16 @@ public function createGitClient( /* create http client */ $httpClient = new GuzzleHttpClient($guzzleOptions); /* create git client */ - return new $clientClass($httpClient, $logger); + $result = new $clientClass($httpClient, $logger); + assert($result instanceof ClientInterface); + + return $result; } /** * Get client class according to URL content - * - * @param string $url - * - * @return string */ - public static function detectClientClass($url) + public static function detectClientClass(string $url): string { $scheme = parse_url($url, PHP_URL_SCHEME); if (!in_array($scheme, ['http', 'https'])) { @@ -159,9 +150,10 @@ public static function detectClientClass($url) } $hostname = parse_url($url, PHP_URL_HOST); + assert('string' === gettype($hostname)); if ('api.github.com' === $hostname || 'github.com' === $hostname) { return GithubClient::class; - } elseif (false !== strpos($hostname, 'gogs')) { + } elseif (str_contains($hostname, 'gogs')) { return GogsClient::class; } /* @@ -176,7 +168,7 @@ public static function detectClientClass($url) */ public static function getInstance() { - if (is_null(self::$instance)) { + if (null == self::$instance) { self::$instance = new ClientFactory(); } @@ -186,11 +178,11 @@ public static function getInstance() /** * Register client type * - * @param string $className + * @param class-string $className * * @SuppressWarnings(PHPMD.StaticAccess) */ - private function register($className) + private function register(string $className): void { $clientProperties = ClientHelper::getStaticProperties($className); $this->types[$clientProperties['typeName']] = $clientProperties; diff --git a/src/ClientInterface.php b/src/ClientInterface.php index f06729f..adbdec8 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -15,7 +15,7 @@ interface ClientInterface * * @return ProjectInterface[] */ - public function find(FindOptions $options); + public function find(FindOptions $options): array; /** * Get raw file @@ -23,12 +23,10 @@ public function find(FindOptions $options); * @param ProjectInterface $project ex : 123456 * @param string $filePath ex : composer.json * @param string $ref ex : master - * - * @return string */ public function getRawFile( ProjectInterface $project, - $filePath, - $ref - ); + string $filePath, + string $ref + ): string; } diff --git a/src/ClientOptions.php b/src/ClientOptions.php index 6a5aa25..95d54e3 100644 --- a/src/ClientOptions.php +++ b/src/ClientOptions.php @@ -12,31 +12,23 @@ class ClientOptions /** * Allows to force a given client type and avoid * detection based on URL - * - * @var string */ - private $type; + private string $type; /** * Base URL (ex : https://gitlab.com) - * - * @var string */ - private $url; + private string $url; /** * Access token - * - * @var string */ - private $token; + private ?string $token; /** * Bypass SSL certificate checks for self signed certificates - * - * @var bool */ - private $unsafeSsl; + private bool $unsafeSsl; public function __construct() { @@ -44,33 +36,25 @@ public function __construct() } /** - * True if client type is specificied - * - * @return bool + * True if client type is specified */ - public function hasType() + public function hasType(): bool { return !empty($this->type); } /** * Get client type - * - * @return string */ - public function getType() + public function getType(): string { return $this->type; } /** - * Set client type - * - * @param string $type gitlab,github,gogs,... - * - * @return self + * Set client type (ex : github, gitlab-v4,...) */ - public function setType($type) + public function setType(string $type): self { $this->type = $type; @@ -78,21 +62,17 @@ public function setType($type) } /** - * @return string + * Get URL */ - public function getUrl() + public function getUrl(): string { return $this->url; } /** * Set URL - * - * @param string $url - * - * @return self */ - public function setUrl($url) + public function setUrl(string $url): self { $this->url = $url; @@ -101,32 +81,24 @@ public function setUrl($url) /** * Is token defined? - * - * @return bool */ - public function hasToken() + public function hasToken(): bool { return !empty($this->token); } /** * Get access token - * - * @return string */ - public function getToken() + public function getToken(): ?string { return $this->token; } /** * Set access token - * - * @param string $token Access token - * - * @return self */ - public function setToken($token) + public function setToken(?string $token): self { $this->token = $token; @@ -134,21 +106,17 @@ public function setToken($token) } /** - * @return bool + * Is unsafeSsl */ - public function isUnsafeSsl() + public function isUnsafeSsl(): bool { return $this->unsafeSsl; } /** * Set unsafeSsl - * - * @param bool $unsafeSsl - * - * @return self */ - public function setUnsafeSsl($unsafeSsl) + public function setUnsafeSsl(bool $unsafeSsl): self { $this->unsafeSsl = $unsafeSsl; diff --git a/src/Exception/ClientNotFoundException.php b/src/Exception/ClientNotFoundException.php index 87bb7d0..ac0c9b9 100644 --- a/src/Exception/ClientNotFoundException.php +++ b/src/Exception/ClientNotFoundException.php @@ -9,7 +9,10 @@ */ class ClientNotFoundException extends RuntimeException { - public function __construct($typeName, $availableTypes = []) + /** + * @param string[] $availableTypes + */ + public function __construct(string $typeName, array $availableTypes = []) { $message = sprintf("type '%s' not found in %s", $typeName, json_encode($availableTypes)); parent::__construct($message); diff --git a/src/Exception/MissingConstException.php b/src/Exception/MissingConstException.php index 3f2ec5a..0157fc9 100644 --- a/src/Exception/MissingConstException.php +++ b/src/Exception/MissingConstException.php @@ -9,7 +9,7 @@ */ class MissingConstException extends RuntimeException { - public function __construct($className, $constName) + public function __construct(string $className, string $constName) { $message = sprintf("Missing const '%s' on class '%s'", $constName, $className); parent::__construct($message); diff --git a/src/Exception/RawFileNotFoundException.php b/src/Exception/RawFileNotFoundException.php new file mode 100644 index 0000000..f476119 --- /dev/null +++ b/src/Exception/RawFileNotFoundException.php @@ -0,0 +1,21 @@ +projectType; } /** * Set filter according to project type - * - * @param string $projectType Filter according to project type - * - * @return self */ - public function setProjectType($projectType) + public function setProjectType(string $projectType): self { $this->projectType = $projectType; @@ -74,9 +63,9 @@ public function setProjectType($projectType) } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { $description = 'composer.json should exists'; if (!empty($this->projectType)) { @@ -87,9 +76,9 @@ public function getDescription() } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function isAccepted(ProjectInterface $project) + public function isAccepted(ProjectInterface $project): bool { try { $branch = $project->getDefaultBranch(); diff --git a/src/Filter/FilterCollection.php b/src/Filter/FilterCollection.php index b57dfc0..6c7b8e5 100644 --- a/src/Filter/FilterCollection.php +++ b/src/Filter/FilterCollection.php @@ -25,8 +25,6 @@ class FilterCollection implements ProjectFilterInterface private $logger; /** - * @param LoggerInterface $logger - * * @SuppressWarnings(PHPMD.StaticAccess) */ public function __construct(LoggerInterface $logger = null) @@ -37,18 +35,18 @@ public function __construct(LoggerInterface $logger = null) /** * Add a filter to the collection - * - * @return void */ - public function addFilter(ProjectFilterInterface $filter) + public function addFilter(ProjectFilterInterface $filter): self { $this->filters[] = $filter; + + return $this; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { $parts = []; foreach ($this->filters as $filter) { @@ -59,9 +57,9 @@ public function getDescription() } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function isAccepted(ProjectInterface $project) + public function isAccepted(ProjectInterface $project): bool { foreach ($this->filters as $filter) { if (!$filter->isAccepted($project)) { @@ -85,10 +83,8 @@ public function isAccepted(ProjectInterface $project) /** * Get filter name - * - * @return string */ - private function getFilterName(ProjectFilterInterface $filter) + private function getFilterName(ProjectFilterInterface $filter): string { $clazz = get_class($filter); $parts = explode('\\', $clazz); diff --git a/src/Filter/IgnoreRegexpFilter.php b/src/Filter/IgnoreRegexpFilter.php index 795939f..b555664 100644 --- a/src/Filter/IgnoreRegexpFilter.php +++ b/src/Filter/IgnoreRegexpFilter.php @@ -15,26 +15,26 @@ class IgnoreRegexpFilter implements ProjectFilterInterface /** * @var string */ - protected $ignoreRegexp; + protected string $ignoreRegexp; - public function __construct($ignoreRegexp) + public function __construct(string $ignoreRegexp) { assert(!empty($ignoreRegexp)); $this->ignoreRegexp = $ignoreRegexp; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { return 'project name should not match /'.$this->ignoreRegexp.'/'; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function isAccepted(ProjectInterface $project) + public function isAccepted(ProjectInterface $project): bool { return !preg_match("/$this->ignoreRegexp/", $project->getName()); } diff --git a/src/Filter/RequiredFileFilter.php b/src/Filter/RequiredFileFilter.php index 1f766ac..a924bbd 100644 --- a/src/Filter/RequiredFileFilter.php +++ b/src/Filter/RequiredFileFilter.php @@ -47,23 +47,27 @@ public function __construct( } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getDescription() + public function getDescription(): string { return sprintf("File '%s' should exist in default branch", $this->filePath); } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function isAccepted(ProjectInterface $project) + public function isAccepted(ProjectInterface $project): bool { + $branch = $project->getDefaultBranch(); + if (is_null($branch)) { + return false; + } try { $this->gitClient->getRawFile( $project, $this->filePath, - $project->getDefaultBranch() + $branch ); return true; diff --git a/src/FindOptions.php b/src/FindOptions.php index 9e5b858..4714d14 100644 --- a/src/FindOptions.php +++ b/src/FindOptions.php @@ -16,29 +16,25 @@ class FindOptions * * @var string[] */ - private $organizations = []; + private array $organizations = []; /** * Filter according to user names * * @var string[] */ - private $users = []; + private array $users = []; /** * Search string (available only for gitlab prefer the use of organizations and users) - * - * @var string */ - private $search; + private string $search; /** * Additional filter that can't be implemented throw * project listing API parameters - * - * @var ProjectFilterInterface */ - private $filter; + private ProjectFilterInterface $filter; public function __construct() { @@ -47,10 +43,8 @@ public function __construct() /** * True if search is defined - * - * @return bool */ - public function hasSearch() + public function hasSearch(): bool { return !empty($this->search); } @@ -60,7 +54,7 @@ public function hasSearch() * * @return string[] */ - public function getOrganizations() + public function getOrganizations(): array { return $this->organizations; } @@ -69,10 +63,8 @@ public function getOrganizations() * Set filter according to organizations * * @param string[] $organizations Filter according to organizations - * - * @return self */ - public function setOrganizations(array $organizations) + public function setOrganizations(array $organizations): self { $this->organizations = $organizations; @@ -84,7 +76,7 @@ public function setOrganizations(array $organizations) * * @return string[] */ - public function getUsers() + public function getUsers(): array { return $this->users; } @@ -93,10 +85,8 @@ public function getUsers() * Set filter according to user names * * @param string[] $users Filter according to user names - * - * @return self */ - public function setUsers(array $users) + public function setUsers(array $users): self { $this->users = $users; @@ -105,22 +95,16 @@ public function setUsers(array $users) /** * Get search string (prefer the use of organizations and users) - * - * @return string */ - public function getSearch() + public function getSearch(): string { return $this->search; } /** * Set search string (prefer the use of organizations and users) - * - * @param string $search Search string (prefer the use of organizations and users) - * - * @return self */ - public function setSearch($search) + public function setSearch(string $search): self { $this->search = $search; @@ -129,22 +113,16 @@ public function setSearch($search) /** * Get project listing API parameters - * - * @return ProjectFilterInterface */ - public function getFilter() + public function getFilter(): ProjectFilterInterface { return $this->filter; } /** * Set project listing API parameters - * - * @param ProjectFilterInterface $filter project listing API parameters - * - * @return self */ - public function setFilter(ProjectFilterInterface $filter) + public function setFilter(ProjectFilterInterface $filter): self { $this->filter = $filter; diff --git a/src/Github/GithubClient.php b/src/Github/GithubClient.php index c3a3155..b1153f2 100644 --- a/src/Github/GithubClient.php +++ b/src/Github/GithubClient.php @@ -2,14 +2,15 @@ namespace MBO\RemoteGit\Github; +use Exception; use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; +use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\Exception\RequiredParameterException; use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\ProjectFilterInterface; -use MBO\RemoteGit\Helper\LoggerHelper; use MBO\RemoteGit\Http\TokenType; /** @@ -53,22 +54,21 @@ public function __construct( GuzzleHttpClient $httpClient, LoggerInterface $logger = null ) { - $this->httpClient = $httpClient; - $this->logger = LoggerHelper::handleNull($logger); + parent::__construct($httpClient, $logger); } /** - * {@inheritdoc} + * {@inheritDoc} */ - protected function createProject(array $rawProject) + protected function createProject(array $rawProject): GithubProject { return new GithubProject($rawProject); } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function find(FindOptions $options) + public function find(FindOptions $options): array { $result = []; if (empty($options->getUsers()) && empty($options->getOrganizations())) { @@ -99,7 +99,7 @@ public function find(FindOptions $options) * @return ProjectInterface[] */ protected function findByUser( - $user, + string $user, ProjectFilterInterface $projectFilter ) { /* @@ -127,7 +127,7 @@ protected function findByUser( * @return ProjectInterface[] */ protected function findByOrg( - $org, + string $org, ProjectFilterInterface $projectFilter ) { return $this->fetchAllPages( @@ -139,15 +139,16 @@ protected function findByOrg( /** * Fetch all pages for a given URI * - * @param string $path such as '/orgs/IGNF/repos' or '/users/mborne/repos' + * @param string $path such as '/orgs/IGNF/repos' or '/users/mborne/repos' + * @param array $extraParams * * @return ProjectInterface[] */ private function fetchAllPages( - $path, + string $path, ProjectFilterInterface $projectFilter, - $extraParams = [] - ) { + array $extraParams = [] + ): array { $result = []; for ($page = 1; $page <= self::MAX_PAGES; ++$page) { $params = array_merge($extraParams, [ @@ -164,14 +165,14 @@ private function fetchAllPages( return $result; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ public function getRawFile( ProjectInterface $project, $filePath, $ref - ) { + ): string { $metadata = $project->getRawMetadata(); $uri = str_replace( '{+path}', @@ -179,13 +180,18 @@ public function getRawFile( $metadata['contents_url'] ); $uri .= '?ref='.$ref; - $this->getLogger()->debug('GET '.$uri); - $response = $this->getHttpClient()->request('GET', $uri, [ - 'headers' => [ - 'Accept' => 'application/vnd.github.v3.raw', - ], - ]); - - return (string) $response->getBody(); + + try { + $this->getLogger()->debug('GET '.$uri); + $response = $this->getHttpClient()->request('GET', $uri, [ + 'headers' => [ + 'Accept' => 'application/vnd.github.v3.raw', + ], + ]); + + return (string) $response->getBody(); + } catch (Exception $e) { + throw new RawFileNotFoundException($filePath, $ref, $e); + } } } diff --git a/src/Github/GithubProject.php b/src/Github/GithubProject.php index 5950899..0e59c34 100644 --- a/src/Github/GithubProject.php +++ b/src/Github/GithubProject.php @@ -11,49 +11,49 @@ */ class GithubProject implements ProjectInterface { - protected $rawMetadata; - - public function __construct($rawMetadata) + /** + * @param array $rawMetadata + */ + public function __construct(private array $rawMetadata) { - $this->rawMetadata = $rawMetadata; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getId() + public function getId(): string { return $this->rawMetadata['id']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getName() + public function getName(): string { return $this->rawMetadata['full_name']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getDefaultBranch() + public function getDefaultBranch(): ?string { return $this->rawMetadata['default_branch']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getHttpUrl() + public function getHttpUrl(): string { return $this->rawMetadata['clone_url']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getRawMetadata() + public function getRawMetadata(): array { return $this->rawMetadata; } diff --git a/src/Gitlab/GitlabClient.php b/src/Gitlab/GitlabClient.php index 07ad195..415aba2 100644 --- a/src/Gitlab/GitlabClient.php +++ b/src/Gitlab/GitlabClient.php @@ -2,9 +2,11 @@ namespace MBO\RemoteGit\Gitlab; +use Exception; use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; +use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\ProjectFilterInterface; @@ -30,9 +32,6 @@ class GitlabClient extends AbstractClient /** * Constructor with an http client and a logger - * - * @param $httpClient http client - * @param $logger */ public function __construct( GuzzleHttpClient $httpClient, @@ -41,18 +40,18 @@ public function __construct( parent::__construct($httpClient, $logger); } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - protected function createProject(array $rawProject) + protected function createProject(array $rawProject): GitlabProject { return new GitlabProject($rawProject); } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function find(FindOptions $options) + public function find(FindOptions $options): array { /* find all projects applying optional search */ if (empty($options->getUsers()) && empty($options->getOrganizations())) { @@ -82,9 +81,9 @@ public function find(FindOptions $options) * @return ProjectInterface[] */ protected function findByUser( - $user, + string $user, ProjectFilterInterface $projectFilter - ) { + ): array { return $this->fetchAllPages( '/api/v4/users/'.urlencode($user).'/projects', [], @@ -98,9 +97,9 @@ protected function findByUser( * @return ProjectInterface[] */ protected function findByGroup( - $group, + string $group, ProjectFilterInterface $projectFilter - ) { + ): array { return $this->fetchAllPages( '/api/v4/groups/'.urlencode($group).'/projects', [], @@ -131,13 +130,13 @@ protected function findBySearch(FindOptions $options) /** * Fetch all pages for a given path with query params * - * @param string $path ex : "/api/v4/projects" - * @param array $params ex : array('search'=>'sample-composer') + * @param string $path ex : "/api/v4/projects" + * @param array $params ex : array('search'=>'sample-composer') * * @return ProjectInterface[] */ private function fetchAllPages( - $path, + string $path, array $params, ProjectFilterInterface $projectFilter ) { @@ -157,20 +156,24 @@ private function fetchAllPages( return $result; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ public function getRawFile( ProjectInterface $project, - $filePath, - $ref - ) { + string $filePath, + string $ref + ): string { // ref : https://docs.gitlab.com/ee/api/repository_files.html#get-raw-file-from-repository $uri = '/api/v4/projects/'.$project->getId().'/repository/files/'.urlencode($filePath).'/raw'; $uri .= '?ref='.$ref; - $this->getLogger()->debug('GET '.$uri); - $response = $this->httpClient->request('GET', $uri); + try { + $this->getLogger()->debug('GET '.$uri); + $response = $this->httpClient->request('GET', $uri); - return (string) $response->getBody(); + return (string) $response->getBody(); + } catch (Exception $e) { + throw new RawFileNotFoundException($filePath, $ref); + } } } diff --git a/src/Gitlab/GitlabProject.php b/src/Gitlab/GitlabProject.php index 874213d..6f66e4a 100644 --- a/src/Gitlab/GitlabProject.php +++ b/src/Gitlab/GitlabProject.php @@ -11,33 +11,33 @@ */ class GitlabProject implements ProjectInterface { - protected $rawMetadata; - - public function __construct($rawMetadata) + /** + * @param array $rawMetadata + */ + public function __construct(private array $rawMetadata) { - $this->rawMetadata = $rawMetadata; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getId() + public function getId(): string { return $this->rawMetadata['id']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getName() + public function getName(): string { return $this->rawMetadata['path_with_namespace']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getDefaultBranch() + public function getDefaultBranch(): ?string { if (!isset($this->rawMetadata['default_branch'])) { return null; @@ -46,18 +46,18 @@ public function getDefaultBranch() return $this->rawMetadata['default_branch']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getHttpUrl() + public function getHttpUrl(): string { return $this->rawMetadata['http_url_to_repo']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getRawMetadata() + public function getRawMetadata(): array { return $this->rawMetadata; } diff --git a/src/Gogs/GogsClient.php b/src/Gogs/GogsClient.php index e93737e..e21fc30 100644 --- a/src/Gogs/GogsClient.php +++ b/src/Gogs/GogsClient.php @@ -2,16 +2,18 @@ namespace MBO\RemoteGit\Gogs; +use Exception; use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; +use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Http\TokenType; /** - * Client implementation for gogs + * Client implementation for gogs and gitea. * * @author mborne */ @@ -22,8 +24,8 @@ class GogsClient extends AbstractClient public const DEFAULT_PER_PAGE = 1000; - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ public function __construct( GuzzleHttpClient $httpClient, @@ -32,18 +34,18 @@ public function __construct( parent::__construct($httpClient, $logger); } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - protected function createProject(array $rawProject) + protected function createProject(array $rawProject): GogsProject { return new GogsProject($rawProject); } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function find(FindOptions $options) + public function find(FindOptions $options): array { if (empty($options->getUsers()) && empty($options->getOrganizations())) { return $this->findByCurrentUser( @@ -75,7 +77,7 @@ public function find(FindOptions $options) */ protected function findByCurrentUser( ProjectFilterInterface $projectFilter - ) { + ): array { return $this->filter( $this->getProjects( '/api/v1/user/repos', @@ -93,9 +95,9 @@ protected function findByCurrentUser( * @return ProjectInterface[] */ protected function findByUser( - $user, + string $user, ProjectFilterInterface $projectFilter - ) { + ): array { return $this->filter( $this->getProjects( '/api/v1/users/'.$user.'/repos', @@ -108,14 +110,14 @@ protected function findByUser( } /** - * Find projects by username + * Find projects by organization * * @return ProjectInterface[] */ protected function findByOrg( - $org, + string $org, ProjectFilterInterface $projectFilter - ) { + ): array { return $this->filter( $this->getProjects( '/api/v1/orgs/'.$org.'/repos', @@ -127,21 +129,25 @@ protected function findByOrg( ); } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ public function getRawFile( ProjectInterface $project, $filePath, $ref - ) { + ): string { $uri = '/api/v1/repos/'.$project->getName().'/raw/'; $uri .= $project->getDefaultBranch(); $uri .= '/'.$filePath; - $this->getLogger()->debug('GET '.$uri); - $response = $this->getHttpClient()->request('GET', $uri); + try { + $this->getLogger()->debug('GET '.$uri); + $response = $this->getHttpClient()->request('GET', $uri); - return (string) $response->getBody(); + return (string) $response->getBody(); + } catch (Exception $e) { + throw new RawFileNotFoundException($filePath, $ref, $e); + } } } diff --git a/src/Gogs/GogsProject.php b/src/Gogs/GogsProject.php index c58a906..e41c86c 100644 --- a/src/Gogs/GogsProject.php +++ b/src/Gogs/GogsProject.php @@ -11,49 +11,49 @@ */ class GogsProject implements ProjectInterface { - protected $rawMetadata; - - public function __construct($rawMetadata) + /** + * @param array $rawMetadata + */ + public function __construct(private array $rawMetadata) { - $this->rawMetadata = $rawMetadata; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getId() + public function getId(): string { return $this->rawMetadata['id']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getName() + public function getName(): string { return $this->rawMetadata['full_name']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getDefaultBranch() + public function getDefaultBranch(): ?string { return $this->rawMetadata['default_branch']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getHttpUrl() + public function getHttpUrl(): string { return $this->rawMetadata['clone_url']; } - /* - * @{inheritDoc} + /** + * {@inheritDoc} */ - public function getRawMetadata() + public function getRawMetadata(): array { return $this->rawMetadata; } diff --git a/src/Helper/ClientHelper.php b/src/Helper/ClientHelper.php index 25ea972..6b461b4 100644 --- a/src/Helper/ClientHelper.php +++ b/src/Helper/ClientHelper.php @@ -15,11 +15,11 @@ class ClientHelper /** * Retrieve TYPE and TOKEN_TYPE from client class * - * @param string $className + * @param class-string $className * * @return string[] */ - public static function getStaticProperties($className) + public static function getStaticProperties(string $className): array { $reflectionClass = new ReflectionClass($className); if (!$reflectionClass->implementsInterface(ClientInterface::class)) { diff --git a/src/Helper/LoggerHelper.php b/src/Helper/LoggerHelper.php index 5956e53..e63d468 100644 --- a/src/Helper/LoggerHelper.php +++ b/src/Helper/LoggerHelper.php @@ -12,14 +12,10 @@ class LoggerHelper { /** * Converts null to NullLogger - * - * @param LoggerInterface $logger - * - * @return LoggerInterface */ public static function handleNull( LoggerInterface $logger = null - ) { + ): LoggerInterface { return is_null($logger) ? new NullLogger() : $logger; } } diff --git a/src/Http/TokenType.php b/src/Http/TokenType.php index a15b170..69934ca 100644 --- a/src/Http/TokenType.php +++ b/src/Http/TokenType.php @@ -14,10 +14,9 @@ class TokenType /** * Create HTTP headers according to a tokenType * - * @param string $tokenType - * @param string $token + * @return array */ - public static function createHttpHeaders($tokenType, $token) + public static function createHttpHeaders(string $tokenType, ?string $token): array { if (empty($token)) { return []; diff --git a/src/Local/LocalClient.php b/src/Local/LocalClient.php index 0880605..07066e8 100644 --- a/src/Local/LocalClient.php +++ b/src/Local/LocalClient.php @@ -4,6 +4,7 @@ use Psr\Log\LoggerInterface; use MBO\RemoteGit\ClientInterface; +use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Helper\LoggerHelper; use MBO\RemoteGit\Http\TokenType; @@ -32,21 +33,18 @@ class LocalClient implements ClientInterface /** * Create a LocalClient for a folder containing a hierarchy of git repositories * - * @param string $rootPath - * @param LoggerInterface $logger - * * @SuppressWarnings(PHPMD.StaticAccess) */ - public function __construct($rootPath, LoggerInterface $logger = null) + public function __construct(string $rootPath, LoggerInterface $logger = null) { - $this->rootPath = realpath($rootPath); + $this->rootPath = $rootPath; $this->logger = LoggerHelper::handleNull($logger); } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function find(FindOptions $options) + public function find(FindOptions $options): array { $projects = []; @@ -97,14 +95,16 @@ public function createLocalProject($projectFolder) * TODO use something like "git rev-parse --git-dir" to validate * folders * - * @param string $parentPath absolute path to a given folder + * @param string $parentPath absolute path to a given folder + * @param string[] $projectFolders * * @SuppressWarnings(PHPMD.ElseExpression) */ - protected function findProjectFolders($parentPath, array &$projectFolders) + protected function findProjectFolders(string $parentPath, array &$projectFolders): void { $this->logger->debug("Checking if $parentPath is a git repository ..."); $items = scandir($parentPath); + assert(false !== $items); foreach ($items as $item) { if ('.' === $item || '..' === $item) { continue; @@ -129,27 +129,40 @@ protected function findProjectFolders($parentPath, array &$projectFolders) } /** - * {@inheritdoc} + * {@inheritDoc} */ public function getRawFile( ProjectInterface $project, - $filePath, - $ref - ) { + string $filePath, + string $ref + ): string { $cmd = sprintf( - 'cd %s ; git show %s:%s', - escapeshellarg($project->getHttpUrl()), + 'git show %s:%s', escapeshellarg($ref), escapeshellarg($filePath) ); - $this->logger->info(sprintf( - 'getRawFile(%s,%s,%s) : %s', - escapeshellarg($project->getHttpUrl()), - escapeshellarg($ref), - escapeshellarg($filePath), - $cmd - )); + $cwd = $project->getHttpUrl(); + + $pipes = []; + $proc = proc_open($cmd, [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ], $pipes, $cwd); + + $stdout = stream_get_contents($pipes[1]); + fclose($pipes[1]); + $stderr = stream_get_contents($pipes[2]); + fclose($pipes[2]); + if (false === $proc || 0 !== proc_close($proc)) { + $this->logger->error(sprintf('command fails : %s', $stderr), [ + 'cmd' => $cmd, + 'cwd' => $cwd, + ]); + throw new RawFileNotFoundException($filePath, $ref); + } + + assert(false !== $stdout); - return shell_exec($cmd); + return $stdout; } } diff --git a/src/Local/LocalProject.php b/src/Local/LocalProject.php index dfc566d..37065f8 100644 --- a/src/Local/LocalProject.php +++ b/src/Local/LocalProject.php @@ -10,51 +10,48 @@ class LocalProject implements ProjectInterface { /** - * @var string[] + * @param array $rawMetadata */ - protected $rawMetadata; - - public function __construct(array $rawMetadata) + public function __construct(private array $rawMetadata) { - $this->rawMetadata = $rawMetadata; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getId() + public function getId(): string { return $this->rawMetadata['id']; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getName() + public function getName(): string { return $this->rawMetadata['full_name']; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getDefaultBranch() + public function getDefaultBranch(): ?string { return $this->rawMetadata['head_branch']; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getHttpUrl() + public function getHttpUrl(): string { return $this->rawMetadata['full_path']; } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getRawMetadata() + public function getRawMetadata(): array { return $this->rawMetadata; } diff --git a/src/ProjectFilterInterface.php b/src/ProjectFilterInterface.php index 1b49bc3..fd2a383 100644 --- a/src/ProjectFilterInterface.php +++ b/src/ProjectFilterInterface.php @@ -11,15 +11,11 @@ interface ProjectFilterInterface { /** * Get filter description (ex : "Project should contains a composer.json file") - * - * @return string */ - public function getDescription(); + public function getDescription(): string; /** * Returns true if the project should be included in satis configuration - * - * @return bool */ - public function isAccepted(ProjectInterface $project); + public function isAccepted(ProjectInterface $project): bool; } diff --git a/src/ProjectInterface.php b/src/ProjectInterface.php index 2b28069..da0e5d5 100644 --- a/src/ProjectInterface.php +++ b/src/ProjectInterface.php @@ -11,36 +11,28 @@ interface ProjectInterface { /** * Get project id - * - * @return string */ - public function getId(); + public function getId(): string; /** * Get project name (with namespace) - * - * @return string */ - public function getName(); + public function getName(): string; /** * Get default branch - * - * @return ?string */ - public function getDefaultBranch(); + public function getDefaultBranch(): ?string; /** * Get http url - * - * @return string */ - public function getHttpUrl(); + public function getHttpUrl(): string; /** * Get hosting service specific properties * - * @return array + * @return array */ - public function getRawMetadata(); + public function getRawMetadata(): array; } diff --git a/tests/ClientFactoryTest.php b/tests/ClientFactoryTest.php index 0cd2acd..f192cb7 100644 --- a/tests/ClientFactoryTest.php +++ b/tests/ClientFactoryTest.php @@ -4,6 +4,7 @@ use MBO\RemoteGit\ClientFactory; use MBO\RemoteGit\ClientOptions; +use MBO\RemoteGit\Exception\ClientNotFoundException; use MBO\RemoteGit\Github\GithubClient; use MBO\RemoteGit\Gitlab\GitlabClient; use MBO\RemoteGit\Gogs\GogsClient; @@ -22,15 +23,20 @@ public function testGetTypes(): void public function testInvalidType(): void { $clientFactory = ClientFactory::getInstance(); - $thrown = false; + $thrown = null; try { $options = new ClientOptions(); $options->setType('missing'); $clientFactory->createGitClient($options); } catch (\Exception $e) { - $thrown = true; + $thrown = $e; } - $this->assertTrue($thrown, 'exception should be thrown'); + $this->assertNotNull($thrown, 'exception should be thrown'); + $this->assertInstanceOf(ClientNotFoundException::class, $thrown); + $this->assertStringStartsWith( + "type 'missing' not found in", + $thrown->getMessage() + ); } public function testDetectClientType(): void diff --git a/tests/Filter/RequiredFileFilterTest.php b/tests/Filter/RequiredFileFilterTest.php index ad4fb1e..36cf01d 100644 --- a/tests/Filter/RequiredFileFilterTest.php +++ b/tests/Filter/RequiredFileFilterTest.php @@ -34,7 +34,7 @@ public function testRequiredFileMissing(): void /** * Accepted if composer.json exists */ - public function testRequiredFilePresent() + public function testRequiredFilePresent(): void { $project = $this->createMockProject('test'); diff --git a/tests/GithubClientTest.php b/tests/GithubClientTest.php index a24aa5c..49ceac7 100644 --- a/tests/GithubClientTest.php +++ b/tests/GithubClientTest.php @@ -69,19 +69,25 @@ public function testUserAndOrgsRepositories(): void ); $project = $projectsByName['mborne/satis-gitlab']; + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); $composer = $client->getRawFile( $project, 'composer.json', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('mborne@users.noreply.github.com', $composer); + /* test getRawFile */ $testFileInSubdirectory = $client->getRawFile( $project, 'tests/TestCase.php', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('class TestCase', $testFileInSubdirectory); + + /* test getRawFile not found */ + $this->ensureThatRawFileNotFoundThrowsException($client, $project); } /** @@ -110,17 +116,19 @@ public function testFilterFile(): void ); $project = $projectsByName['mborne/satis-gitlab']; + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); $composer = $client->getRawFile( $project, 'composer.json', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('mborne@users.noreply.github.com', $composer); $testFileInSubdirectory = $client->getRawFile( $project, 'tests/TestCase.php', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('class TestCase', $testFileInSubdirectory); } diff --git a/tests/GitlabClientTest.php b/tests/GitlabClientTest.php index ec091d9..c260c65 100644 --- a/tests/GitlabClientTest.php +++ b/tests/GitlabClientTest.php @@ -63,10 +63,12 @@ public function testGitlabDotComByUser(): void ); $project = $projectsByName['mborne/sample-composer']; + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); $composer = $client->getRawFile( $project, 'composer.json', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('mborne@users.noreply.github.com', $composer); } @@ -116,12 +118,18 @@ public function testGitlabDotComSearch(): void $projectsByName ); + /* test getRawFile */ $project = $projectsByName['mborne/sample-composer']; + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); $composer = $client->getRawFile( $project, 'composer.json', - $project->getDefaultBranch() + $defaultBranch ); $this->assertStringContainsString('mborne@users.noreply.github.com', $composer); + + /* test getRawFile not found */ + $this->ensureThatRawFileNotFoundThrowsException($client, $project); } } diff --git a/tests/GogsClientTest.php b/tests/GogsClientTest.php index e8d6819..9363456 100644 --- a/tests/GogsClientTest.php +++ b/tests/GogsClientTest.php @@ -66,6 +66,8 @@ public function testFindByCurrentUser(): void 'docker/docker-php-sury', $projectsByName ); + + /* test getRawFile */ $project = $projectsByName['docker/docker-php-sury']; $this->assertStringContainsString( 'FROM ', @@ -75,6 +77,9 @@ public function testFindByCurrentUser(): void 'ServerTokens Prod', $client->getRawFile($project, 'conf/apache-security.conf', 'master') ); + + /* test getRawFile not found */ + $this->ensureThatRawFileNotFoundThrowsException($client, $project); } /** diff --git a/tests/LocalClientTest.php b/tests/LocalClientTest.php index 84eefb4..e0d6649 100644 --- a/tests/LocalClientTest.php +++ b/tests/LocalClientTest.php @@ -25,7 +25,9 @@ public static function setUpBeforeClass(): void } $fs->mkdir(self::TEMP_DIR); $fs->mkdir(self::TEMP_DIR.'/mborne'); + // non bare repository exec('cd '.self::TEMP_DIR.'/mborne && git clone https://github.com/mborne/remote-git.git'); + // bare repository exec('cd '.self::TEMP_DIR.'/mborne && git clone --bare https://github.com/mborne/satis-gitlab.git'); } @@ -35,11 +37,9 @@ public static function setUpBeforeClass(): void protected function createLocalClient(): LocalClient { // folder containing mborne/remote-git and mborne/satis-gitlab - $rootPath = realpath(self::TEMP_DIR); - $clientOptions = new ClientOptions(); $clientOptions - ->setUrl($rootPath) + ->setUrl(self::TEMP_DIR) ; /* create client */ @@ -94,13 +94,16 @@ public function testFindAll(): void */ public function testGetRawFileFromNonBareRepository(): void { + /* test getRawFile */ $client = $this->createLocalClient(); $project = $client->createLocalProject(self::TEMP_DIR.'/mborne/remote-git'); - $readmeContent = $client->getRawFile($project, 'README.md', $project->getDefaultBranch()); + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); + $readmeContent = $client->getRawFile($project, 'README.md', $defaultBranch); $this->assertStringContainsString('# mborne/remote-git', $readmeContent); - $testCaseContent = $client->getRawFile($project, 'tests/TestCase.php', $project->getDefaultBranch()); - $this->assertStringContainsString('class TestCase', $testCaseContent); + /* test getRawFile not found */ + $this->ensureThatRawFileNotFoundThrowsException($client, $project); } /** @@ -108,12 +111,15 @@ public function testGetRawFileFromNonBareRepository(): void */ public function testGetRawFileFromBareRepository(): void { + /* test getRawFile */ $client = $this->createLocalClient(); $project = $client->createLocalProject(self::TEMP_DIR.'/mborne/satis-gitlab.git'); - $readmeContent = $client->getRawFile($project, 'composer.json', $project->getDefaultBranch()); + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); + $readmeContent = $client->getRawFile($project, 'composer.json', $defaultBranch); $this->assertStringContainsString('symfony/console', $readmeContent); - $testCaseContent = $client->getRawFile($project, 'tests/TestCase.php', $project->getDefaultBranch()); - $this->assertStringContainsString('class TestCase', $testCaseContent); + /* test getRawFile not found */ + $this->ensureThatRawFileNotFoundThrowsException($client, $project); } } diff --git a/tests/TestCase.php b/tests/TestCase.php index d7c05e9..c2b48e2 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,6 +2,9 @@ namespace MBO\RemoteGit\Tests; +use Exception; +use MBO\RemoteGit\ClientInterface; +use MBO\RemoteGit\Exception\RawFileNotFoundException; use PHPUnit\Framework\TestCase as BaseTestCase; use MBO\RemoteGit\ProjectInterface; @@ -41,4 +44,29 @@ protected function assertGettersWorks(ProjectInterface $project): void $this->assertNotEmpty($project->getHttpUrl()); $this->assertNotEmpty($project->getRawMetadata()); } + + /** + * Try to access NOT-FOUND.md on default branch and check RawFileNotFoundException. + */ + protected function ensureThatRawFileNotFoundThrowsException( + ClientInterface $client, + ProjectInterface $project + ): void { + $defaultBranch = $project->getDefaultBranch(); + $this->assertNotNull($defaultBranch); + + // try to retrieve missing file + $thrown = null; + try { + $client->getRawFile($project, 'NOT-FOUND.md', $defaultBranch); + } catch (Exception $e) { + $thrown = $e; + } + $this->assertNotNull($thrown); + $this->assertInstanceOf(RawFileNotFoundException::class, $thrown); + $this->assertEquals( + "file 'NOT-FOUND.md' not found on branch '".$defaultBranch."'", + $thrown->getMessage() + ); + } } From 621f1ee9fb368de15ee1631d1e95eb7e46aa039e Mon Sep 17 00:00:00 2001 From: mborne Date: Mon, 11 Mar 2024 16:12:36 +0100 Subject: [PATCH 6/8] chore(style): use Symfony rules for php-cs-fixer (refs #25) --- Makefile | 2 +- src/AbstractClient.php | 22 +++++--------- src/ClientFactory.php | 20 ++++++------- src/ClientInterface.php | 6 ++-- src/ClientOptions.php | 28 +++++++++--------- src/Exception/ClientNotFoundException.php | 6 ++-- src/Exception/MissingConstException.php | 6 ++-- src/Exception/RawFileNotFoundException.php | 9 ++---- src/Exception/RequiredParameterException.php | 6 ++-- src/Filter/ComposerProjectFilter.php | 18 ++++-------- src/Filter/FilterCollection.php | 18 ++++-------- src/Filter/IgnoreRegexpFilter.php | 13 ++------- src/Filter/RequiredFileFilter.php | 14 +++------ src/FindOptions.php | 28 +++++++++--------- src/Github/GithubClient.php | 27 ++++++------------ src/Github/GithubProject.php | 17 +---------- src/Gitlab/GitlabClient.php | 30 +++++++------------- src/Gitlab/GitlabProject.php | 17 +---------- src/Gogs/GogsClient.php | 27 +++++------------- src/Gogs/GogsProject.php | 17 +---------- src/Helper/ClientHelper.php | 7 ++--- src/Helper/LoggerHelper.php | 4 +-- src/Http/TokenType.php | 4 +-- src/Local/LocalClient.php | 16 ++++------- src/Local/LocalProject.php | 17 +---------- src/ProjectFilterInterface.php | 6 ++-- src/ProjectInterface.php | 12 ++++---- tests/Filter/ComposerProjectFilterTest.php | 12 ++++---- tests/Filter/FilterCollectionTest.php | 10 +++---- tests/Filter/IgnoreRegexpFilterTest.php | 4 +-- tests/Filter/RequiredFileFilterTest.php | 8 +++--- tests/GithubClientTest.php | 10 +++---- tests/GitlabClientTest.php | 8 +++--- tests/GogsClientTest.php | 6 ++-- tests/Http/TokenTypeTest.php | 2 +- tests/LocalClientTest.php | 16 +++++------ tests/TestCase.php | 9 +++--- 37 files changed, 168 insertions(+), 314 deletions(-) diff --git a/Makefile b/Makefile index bb45e55..87430eb 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PHP_CS_RULES=@Symfony,-ordered_imports,-phpdoc_summary,-global_namespace_import,-no_superfluous_phpdoc_tags +PHP_CS_RULES=@Symfony PHP_MD_RULES=cleancode,codesize,controversial,design,naming,unusedcode .PHONY: test diff --git a/src/AbstractClient.php b/src/AbstractClient.php index 67478dd..d1292ef 100644 --- a/src/AbstractClient.php +++ b/src/AbstractClient.php @@ -2,13 +2,13 @@ namespace MBO\RemoteGit; -use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\Helper\LoggerHelper; +use Psr\Log\LoggerInterface; /** * Abstract class providing a framework to implement clients - * based on API + * based on API. */ abstract class AbstractClient implements ClientInterface { @@ -23,7 +23,7 @@ abstract class AbstractClient implements ClientInterface protected $logger; /** - * Constructor with an httpClient ready to performs API requests + * Constructor with an httpClient ready to performs API requests. * * @param LoggerInterface $logger * @@ -37,33 +37,25 @@ protected function __construct( $this->logger = LoggerHelper::handleNull($logger); } - /** - * @return GuzzleHttpClient - */ protected function getHttpClient(): GuzzleHttpClient { return $this->httpClient; } - /** - * @return LoggerInterface - */ protected function getLogger(): LoggerInterface { return $this->logger; } /** - * Create a project according to JSON metadata provided by an API + * Create a project according to JSON metadata provided by an API. * * @param array $rawProject - * - * @return ProjectInterface */ abstract protected function createProject(array $rawProject): ProjectInterface; /** - * Get projets for a given path with parameters + * Get projets for a given path with parameters. * * @param array $params * @@ -86,7 +78,7 @@ protected function getProjects( } /** - * Implode params to performs HTTP request + * Implode params to performs HTTP request. * * @param array $params key=>value */ @@ -101,7 +93,7 @@ protected function implodeParams(array $params): string } /** - * Helper to apply filter to a project list + * Helper to apply filter to a project list. * * @param ProjectInterface[] $projects * diff --git a/src/ClientFactory.php b/src/ClientFactory.php index 2fe045c..3c7de17 100644 --- a/src/ClientFactory.php +++ b/src/ClientFactory.php @@ -2,16 +2,16 @@ namespace MBO\RemoteGit; -use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\Exception\ClientNotFoundException; -use MBO\RemoteGit\Helper\LoggerHelper; -use MBO\RemoteGit\Http\TokenType; use MBO\RemoteGit\Github\GithubClient; use MBO\RemoteGit\Gitlab\GitlabClient; use MBO\RemoteGit\Gogs\GogsClient; use MBO\RemoteGit\Helper\ClientHelper; +use MBO\RemoteGit\Helper\LoggerHelper; +use MBO\RemoteGit\Http\TokenType; use MBO\RemoteGit\Local\LocalClient; +use Psr\Log\LoggerInterface; /** * Helper to create clients according to URL. @@ -28,7 +28,7 @@ class ClientFactory private static $instance; /** - * Associates client type to metadata ('className','tokenType') + * Associates client type to metadata ('className','tokenType'). * * @var array> */ @@ -43,7 +43,7 @@ private function __construct() } /** - * True if type is registred + * True if type is registred. * * @param string $type * @@ -55,7 +55,7 @@ public function hasType($type) } /** - * Get supported types + * Get supported types. * * @return string[] */ @@ -65,7 +65,7 @@ public function getTypes() } /** - * Create a client with options + * Create a client with options. */ public static function createClient( ClientOptions $options, @@ -75,7 +75,7 @@ public static function createClient( } /** - * Create a client with options + * Create a client with options. * * @SuppressWarnings(PHPMD.StaticAccess) */ @@ -140,7 +140,7 @@ public function createGitClient( } /** - * Get client class according to URL content + * Get client class according to URL content. */ public static function detectClientClass(string $url): string { @@ -176,7 +176,7 @@ public static function getInstance() } /** - * Register client type + * Register client type. * * @param class-string $className * diff --git a/src/ClientInterface.php b/src/ClientInterface.php index adbdec8..b3c30ae 100644 --- a/src/ClientInterface.php +++ b/src/ClientInterface.php @@ -4,21 +4,21 @@ /** * Lightweight client interface to list hosted git project - * and access files such as composer.json + * and access files such as composer.json. * * @author mborne */ interface ClientInterface { /** - * Find projects throw API + * Find projects throw API. * * @return ProjectInterface[] */ public function find(FindOptions $options): array; /** - * Get raw file + * Get raw file. * * @param ProjectInterface $project ex : 123456 * @param string $filePath ex : composer.json diff --git a/src/ClientOptions.php b/src/ClientOptions.php index 95d54e3..8652f59 100644 --- a/src/ClientOptions.php +++ b/src/ClientOptions.php @@ -3,7 +3,7 @@ namespace MBO\RemoteGit; /** - * Git connection options + * Git connection options. * * @author mborne */ @@ -11,22 +11,22 @@ class ClientOptions { /** * Allows to force a given client type and avoid - * detection based on URL + * detection based on URL. */ private string $type; /** - * Base URL (ex : https://gitlab.com) + * Base URL (ex : https://gitlab.com). */ private string $url; /** - * Access token + * Access token. */ private ?string $token; /** - * Bypass SSL certificate checks for self signed certificates + * Bypass SSL certificate checks for self signed certificates. */ private bool $unsafeSsl; @@ -36,7 +36,7 @@ public function __construct() } /** - * True if client type is specified + * True if client type is specified. */ public function hasType(): bool { @@ -44,7 +44,7 @@ public function hasType(): bool } /** - * Get client type + * Get client type. */ public function getType(): string { @@ -52,7 +52,7 @@ public function getType(): string } /** - * Set client type (ex : github, gitlab-v4,...) + * Set client type (ex : github, gitlab-v4,...). */ public function setType(string $type): self { @@ -62,7 +62,7 @@ public function setType(string $type): self } /** - * Get URL + * Get URL. */ public function getUrl(): string { @@ -70,7 +70,7 @@ public function getUrl(): string } /** - * Set URL + * Set URL. */ public function setUrl(string $url): self { @@ -88,7 +88,7 @@ public function hasToken(): bool } /** - * Get access token + * Get access token. */ public function getToken(): ?string { @@ -96,7 +96,7 @@ public function getToken(): ?string } /** - * Set access token + * Set access token. */ public function setToken(?string $token): self { @@ -106,7 +106,7 @@ public function setToken(?string $token): self } /** - * Is unsafeSsl + * Is unsafeSsl. */ public function isUnsafeSsl(): bool { @@ -114,7 +114,7 @@ public function isUnsafeSsl(): bool } /** - * Set unsafeSsl + * Set unsafeSsl. */ public function setUnsafeSsl(bool $unsafeSsl): self { diff --git a/src/Exception/ClientNotFoundException.php b/src/Exception/ClientNotFoundException.php index ac0c9b9..26c7302 100644 --- a/src/Exception/ClientNotFoundException.php +++ b/src/Exception/ClientNotFoundException.php @@ -2,12 +2,10 @@ namespace MBO\RemoteGit\Exception; -use RuntimeException; - /** - * Custom exception for missing client type + * Custom exception for missing client type. */ -class ClientNotFoundException extends RuntimeException +class ClientNotFoundException extends \RuntimeException { /** * @param string[] $availableTypes diff --git a/src/Exception/MissingConstException.php b/src/Exception/MissingConstException.php index 0157fc9..1148cde 100644 --- a/src/Exception/MissingConstException.php +++ b/src/Exception/MissingConstException.php @@ -2,12 +2,10 @@ namespace MBO\RemoteGit\Exception; -use RuntimeException; - /** - * Custom exception for missing parameters + * Custom exception for missing parameters. */ -class MissingConstException extends RuntimeException +class MissingConstException extends \RuntimeException { public function __construct(string $className, string $constName) { diff --git a/src/Exception/RawFileNotFoundException.php b/src/Exception/RawFileNotFoundException.php index f476119..1566300 100644 --- a/src/Exception/RawFileNotFoundException.php +++ b/src/Exception/RawFileNotFoundException.php @@ -2,18 +2,15 @@ namespace MBO\RemoteGit\Exception; -use RuntimeException; -use Throwable; - /** - * Custom exception for missing raw file + * Custom exception for missing raw file. */ -class RawFileNotFoundException extends RuntimeException +class RawFileNotFoundException extends \RuntimeException { public function __construct( string $filePath, string $ref, - Throwable $previous = null + \Throwable $previous = null ) { $message = sprintf("file '%s' not found on branch '%s'", $filePath, $ref); parent::__construct($message, 404, $previous); diff --git a/src/Exception/RequiredParameterException.php b/src/Exception/RequiredParameterException.php index 57ba83f..13942cd 100644 --- a/src/Exception/RequiredParameterException.php +++ b/src/Exception/RequiredParameterException.php @@ -2,12 +2,10 @@ namespace MBO\RemoteGit\Exception; -use RuntimeException; - /** - * Custom exception for missing parameters + * Custom exception for missing parameters. */ -class RequiredParameterException extends RuntimeException +class RequiredParameterException extends \RuntimeException { public function __construct(string $message = 'missing required parameter') { diff --git a/src/Filter/ComposerProjectFilter.php b/src/Filter/ComposerProjectFilter.php index 9bc8829..53e5ffa 100644 --- a/src/Filter/ComposerProjectFilter.php +++ b/src/Filter/ComposerProjectFilter.php @@ -2,11 +2,11 @@ namespace MBO\RemoteGit\Filter; -use Psr\Log\LoggerInterface; -use MBO\RemoteGit\ProjectInterface; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\ClientInterface as GitClientInterface; use MBO\RemoteGit\Helper\LoggerHelper; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** * Filter projects ensuring that composer.json is present. Optionally, @@ -25,7 +25,7 @@ class ComposerProjectFilter implements ProjectFilterInterface protected LoggerInterface $logger; /** - * Filter according to project type + * Filter according to project type. */ protected string $projectType; @@ -45,7 +45,7 @@ public function __construct( } /** - * Get filter according to project type + * Get filter according to project type. */ public function getProjectType(): string { @@ -53,7 +53,7 @@ public function getProjectType(): string } /** - * Set filter according to project type + * Set filter according to project type. */ public function setProjectType(string $projectType): self { @@ -62,9 +62,6 @@ public function setProjectType(string $projectType): self return $this; } - /** - * {@inheritDoc} - */ public function getDescription(): string { $description = 'composer.json should exists'; @@ -75,9 +72,6 @@ public function getDescription(): string return $description; } - /** - * {@inheritDoc} - */ public function isAccepted(ProjectInterface $project): bool { try { diff --git a/src/Filter/FilterCollection.php b/src/Filter/FilterCollection.php index 6c7b8e5..272c657 100644 --- a/src/Filter/FilterCollection.php +++ b/src/Filter/FilterCollection.php @@ -2,13 +2,13 @@ namespace MBO\RemoteGit\Filter; -use Psr\Log\LoggerInterface; -use MBO\RemoteGit\ProjectInterface; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Helper\LoggerHelper; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** - * Compose a list of filter to simplify command line integration + * Compose a list of filter to simplify command line integration. * * @author mborne */ @@ -34,7 +34,7 @@ public function __construct(LoggerInterface $logger = null) } /** - * Add a filter to the collection + * Add a filter to the collection. */ public function addFilter(ProjectFilterInterface $filter): self { @@ -43,9 +43,6 @@ public function addFilter(ProjectFilterInterface $filter): self return $this; } - /** - * {@inheritDoc} - */ public function getDescription(): string { $parts = []; @@ -56,9 +53,6 @@ public function getDescription(): string return implode(PHP_EOL, $parts); } - /** - * {@inheritDoc} - */ public function isAccepted(ProjectInterface $project): bool { foreach ($this->filters as $filter) { @@ -82,7 +76,7 @@ public function isAccepted(ProjectInterface $project): bool } /** - * Get filter name + * Get filter name. */ private function getFilterName(ProjectFilterInterface $filter): string { diff --git a/src/Filter/IgnoreRegexpFilter.php b/src/Filter/IgnoreRegexpFilter.php index b555664..cef57dd 100644 --- a/src/Filter/IgnoreRegexpFilter.php +++ b/src/Filter/IgnoreRegexpFilter.php @@ -2,19 +2,16 @@ namespace MBO\RemoteGit\Filter; -use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; /** - * Ignore project if project.name matches a given regular expression + * Ignore project if project.name matches a given regular expression. * * @author mborne */ class IgnoreRegexpFilter implements ProjectFilterInterface { - /** - * @var string - */ protected string $ignoreRegexp; public function __construct(string $ignoreRegexp) @@ -23,17 +20,11 @@ public function __construct(string $ignoreRegexp) $this->ignoreRegexp = $ignoreRegexp; } - /** - * {@inheritDoc} - */ public function getDescription(): string { return 'project name should not match /'.$this->ignoreRegexp.'/'; } - /** - * {@inheritDoc} - */ public function isAccepted(ProjectInterface $project): bool { return !preg_match("/$this->ignoreRegexp/", $project->getName()); diff --git a/src/Filter/RequiredFileFilter.php b/src/Filter/RequiredFileFilter.php index a924bbd..b94a272 100644 --- a/src/Filter/RequiredFileFilter.php +++ b/src/Filter/RequiredFileFilter.php @@ -2,14 +2,14 @@ namespace MBO\RemoteGit\Filter; -use Psr\Log\LoggerInterface; -use MBO\RemoteGit\ProjectInterface; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\ClientInterface as GitClientInterface; use MBO\RemoteGit\Helper\LoggerHelper; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** - * Accept projects if git repository contains a given file in default branch + * Accept projects if git repository contains a given file in default branch. * * @author mborne */ @@ -46,17 +46,11 @@ public function __construct( $this->logger = LoggerHelper::handleNull($logger); } - /** - * {@inheritDoc} - */ public function getDescription(): string { return sprintf("File '%s' should exist in default branch", $this->filePath); } - /** - * {@inheritDoc} - */ public function isAccepted(ProjectInterface $project): bool { $branch = $project->getDefaultBranch(); diff --git a/src/FindOptions.php b/src/FindOptions.php index 4714d14..dc21a4a 100644 --- a/src/FindOptions.php +++ b/src/FindOptions.php @@ -5,34 +5,34 @@ use MBO\RemoteGit\Filter\FilterCollection; /** - * Find options to filter project listing + * Find options to filter project listing. * * @author mborne */ class FindOptions { /** - * Filter according to organizations + * Filter according to organizations. * * @var string[] */ private array $organizations = []; /** - * Filter according to user names + * Filter according to user names. * * @var string[] */ private array $users = []; /** - * Search string (available only for gitlab prefer the use of organizations and users) + * Search string (available only for gitlab prefer the use of organizations and users). */ private string $search; /** * Additional filter that can't be implemented throw - * project listing API parameters + * project listing API parameters. */ private ProjectFilterInterface $filter; @@ -42,7 +42,7 @@ public function __construct() } /** - * True if search is defined + * True if search is defined. */ public function hasSearch(): bool { @@ -50,7 +50,7 @@ public function hasSearch(): bool } /** - * Get filter according to organizations + * Get filter according to organizations. * * @return string[] */ @@ -60,7 +60,7 @@ public function getOrganizations(): array } /** - * Set filter according to organizations + * Set filter according to organizations. * * @param string[] $organizations Filter according to organizations */ @@ -72,7 +72,7 @@ public function setOrganizations(array $organizations): self } /** - * Get filter according to user names + * Get filter according to user names. * * @return string[] */ @@ -82,7 +82,7 @@ public function getUsers(): array } /** - * Set filter according to user names + * Set filter according to user names. * * @param string[] $users Filter according to user names */ @@ -94,7 +94,7 @@ public function setUsers(array $users): self } /** - * Get search string (prefer the use of organizations and users) + * Get search string (prefer the use of organizations and users). */ public function getSearch(): string { @@ -102,7 +102,7 @@ public function getSearch(): string } /** - * Set search string (prefer the use of organizations and users) + * Set search string (prefer the use of organizations and users). */ public function setSearch(string $search): self { @@ -112,7 +112,7 @@ public function setSearch(string $search): self } /** - * Get project listing API parameters + * Get project listing API parameters. */ public function getFilter(): ProjectFilterInterface { @@ -120,7 +120,7 @@ public function getFilter(): ProjectFilterInterface } /** - * Set project listing API parameters + * Set project listing API parameters. */ public function setFilter(ProjectFilterInterface $filter): self { diff --git a/src/Github/GithubClient.php b/src/Github/GithubClient.php index b1153f2..08a1f29 100644 --- a/src/Github/GithubClient.php +++ b/src/Github/GithubClient.php @@ -2,19 +2,18 @@ namespace MBO\RemoteGit\Github; -use Exception; -use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\Exception\RequiredParameterException; -use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Http\TokenType; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** - * Client implementation for github + * Client implementation for github. * * See following github docs : * @@ -43,10 +42,9 @@ class GithubClient extends AbstractClient protected $logger; /** - * Constructor with an http client and a logger + * Constructor with an http client and a logger. * * @param $httpClient http client - * @param $logger * * @SuppressWarnings(PHPMD.StaticAccess) */ @@ -57,17 +55,11 @@ public function __construct( parent::__construct($httpClient, $logger); } - /** - * {@inheritDoc} - */ protected function createProject(array $rawProject): GithubProject { return new GithubProject($rawProject); } - /** - * {@inheritDoc} - */ public function find(FindOptions $options): array { $result = []; @@ -122,7 +114,7 @@ protected function findByUser( } /** - * Find projects by username + * Find projects by username. * * @return ProjectInterface[] */ @@ -137,7 +129,7 @@ protected function findByOrg( } /** - * Fetch all pages for a given URI + * Fetch all pages for a given URI. * * @param string $path such as '/orgs/IGNF/repos' or '/users/mborne/repos' * @param array $extraParams @@ -165,9 +157,6 @@ private function fetchAllPages( return $result; } - /** - * {@inheritDoc} - */ public function getRawFile( ProjectInterface $project, $filePath, @@ -190,7 +179,7 @@ public function getRawFile( ]); return (string) $response->getBody(); - } catch (Exception $e) { + } catch (\Exception $e) { throw new RawFileNotFoundException($filePath, $ref, $e); } } diff --git a/src/Github/GithubProject.php b/src/Github/GithubProject.php index 0e59c34..94350bc 100644 --- a/src/Github/GithubProject.php +++ b/src/Github/GithubProject.php @@ -5,7 +5,7 @@ use MBO\RemoteGit\ProjectInterface; /** - * Project implementation for github + * Project implementation for github. * * @author mborne */ @@ -18,41 +18,26 @@ public function __construct(private array $rawMetadata) { } - /** - * {@inheritDoc} - */ public function getId(): string { return $this->rawMetadata['id']; } - /** - * {@inheritDoc} - */ public function getName(): string { return $this->rawMetadata['full_name']; } - /** - * {@inheritDoc} - */ public function getDefaultBranch(): ?string { return $this->rawMetadata['default_branch']; } - /** - * {@inheritDoc} - */ public function getHttpUrl(): string { return $this->rawMetadata['clone_url']; } - /** - * {@inheritDoc} - */ public function getRawMetadata(): array { return $this->rawMetadata; diff --git a/src/Gitlab/GitlabClient.php b/src/Gitlab/GitlabClient.php index 415aba2..34e6c49 100644 --- a/src/Gitlab/GitlabClient.php +++ b/src/Gitlab/GitlabClient.php @@ -2,18 +2,17 @@ namespace MBO\RemoteGit\Gitlab; -use Exception; -use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; use MBO\RemoteGit\Exception\RawFileNotFoundException; -use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Http\TokenType; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** - * Find gitlab projects + * Find gitlab projects. * * See following gitlab docs : * @@ -31,7 +30,7 @@ class GitlabClient extends AbstractClient public const MAX_PAGES = 10000; /** - * Constructor with an http client and a logger + * Constructor with an http client and a logger. */ public function __construct( GuzzleHttpClient $httpClient, @@ -40,17 +39,11 @@ public function __construct( parent::__construct($httpClient, $logger); } - /** - * {@inheritDoc} - */ protected function createProject(array $rawProject): GitlabProject { return new GitlabProject($rawProject); } - /** - * {@inheritDoc} - */ public function find(FindOptions $options): array { /* find all projects applying optional search */ @@ -76,7 +69,7 @@ public function find(FindOptions $options): array } /** - * Find projects by username + * Find projects by username. * * @return ProjectInterface[] */ @@ -92,7 +85,7 @@ protected function findByUser( } /** - * Find projects by group + * Find projects by group. * * @return ProjectInterface[] */ @@ -108,7 +101,7 @@ protected function findByGroup( } /** - * Find all projects using option search + * Find all projects using option search. * * @return ProjectInterface[] */ @@ -128,7 +121,7 @@ protected function findBySearch(FindOptions $options) } /** - * Fetch all pages for a given path with query params + * Fetch all pages for a given path with query params. * * @param string $path ex : "/api/v4/projects" * @param array $params ex : array('search'=>'sample-composer') @@ -156,9 +149,6 @@ private function fetchAllPages( return $result; } - /** - * {@inheritDoc} - */ public function getRawFile( ProjectInterface $project, string $filePath, @@ -172,7 +162,7 @@ public function getRawFile( $response = $this->httpClient->request('GET', $uri); return (string) $response->getBody(); - } catch (Exception $e) { + } catch (\Exception $e) { throw new RawFileNotFoundException($filePath, $ref); } } diff --git a/src/Gitlab/GitlabProject.php b/src/Gitlab/GitlabProject.php index 6f66e4a..0b9eece 100644 --- a/src/Gitlab/GitlabProject.php +++ b/src/Gitlab/GitlabProject.php @@ -5,7 +5,7 @@ use MBO\RemoteGit\ProjectInterface; /** - * Common project properties between different git project host (gitlab, github, etc.) + * Common project properties between different git project host (gitlab, github, etc.). * * @author mborne */ @@ -18,25 +18,16 @@ public function __construct(private array $rawMetadata) { } - /** - * {@inheritDoc} - */ public function getId(): string { return $this->rawMetadata['id']; } - /** - * {@inheritDoc} - */ public function getName(): string { return $this->rawMetadata['path_with_namespace']; } - /** - * {@inheritDoc} - */ public function getDefaultBranch(): ?string { if (!isset($this->rawMetadata['default_branch'])) { @@ -46,17 +37,11 @@ public function getDefaultBranch(): ?string return $this->rawMetadata['default_branch']; } - /** - * {@inheritDoc} - */ public function getHttpUrl(): string { return $this->rawMetadata['http_url_to_repo']; } - /** - * {@inheritDoc} - */ public function getRawMetadata(): array { return $this->rawMetadata; diff --git a/src/Gogs/GogsClient.php b/src/Gogs/GogsClient.php index e21fc30..d3f738f 100644 --- a/src/Gogs/GogsClient.php +++ b/src/Gogs/GogsClient.php @@ -2,15 +2,14 @@ namespace MBO\RemoteGit\Gogs; -use Exception; -use Psr\Log\LoggerInterface; use GuzzleHttp\Client as GuzzleHttpClient; use MBO\RemoteGit\AbstractClient; use MBO\RemoteGit\Exception\RawFileNotFoundException; -use MBO\RemoteGit\ProjectInterface; use MBO\RemoteGit\FindOptions; -use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Http\TokenType; +use MBO\RemoteGit\ProjectFilterInterface; +use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** * Client implementation for gogs and gitea. @@ -24,9 +23,6 @@ class GogsClient extends AbstractClient public const DEFAULT_PER_PAGE = 1000; - /** - * {@inheritDoc} - */ public function __construct( GuzzleHttpClient $httpClient, LoggerInterface $logger = null @@ -34,17 +30,11 @@ public function __construct( parent::__construct($httpClient, $logger); } - /** - * {@inheritDoc} - */ protected function createProject(array $rawProject): GogsProject { return new GogsProject($rawProject); } - /** - * {@inheritDoc} - */ public function find(FindOptions $options): array { if (empty($options->getUsers()) && empty($options->getOrganizations())) { @@ -71,7 +61,7 @@ public function find(FindOptions $options): array } /** - * Find projects for current user + * Find projects for current user. * * @return ProjectInterface[] */ @@ -90,7 +80,7 @@ protected function findByCurrentUser( } /** - * Find projects by username + * Find projects by username. * * @return ProjectInterface[] */ @@ -110,7 +100,7 @@ protected function findByUser( } /** - * Find projects by organization + * Find projects by organization. * * @return ProjectInterface[] */ @@ -129,9 +119,6 @@ protected function findByOrg( ); } - /** - * {@inheritDoc} - */ public function getRawFile( ProjectInterface $project, $filePath, @@ -146,7 +133,7 @@ public function getRawFile( $response = $this->getHttpClient()->request('GET', $uri); return (string) $response->getBody(); - } catch (Exception $e) { + } catch (\Exception $e) { throw new RawFileNotFoundException($filePath, $ref, $e); } } diff --git a/src/Gogs/GogsProject.php b/src/Gogs/GogsProject.php index e41c86c..6a5626d 100644 --- a/src/Gogs/GogsProject.php +++ b/src/Gogs/GogsProject.php @@ -5,7 +5,7 @@ use MBO\RemoteGit\ProjectInterface; /** - * Project implementation for github + * Project implementation for github. * * @author mborne */ @@ -18,41 +18,26 @@ public function __construct(private array $rawMetadata) { } - /** - * {@inheritDoc} - */ public function getId(): string { return $this->rawMetadata['id']; } - /** - * {@inheritDoc} - */ public function getName(): string { return $this->rawMetadata['full_name']; } - /** - * {@inheritDoc} - */ public function getDefaultBranch(): ?string { return $this->rawMetadata['default_branch']; } - /** - * {@inheritDoc} - */ public function getHttpUrl(): string { return $this->rawMetadata['clone_url']; } - /** - * {@inheritDoc} - */ public function getRawMetadata(): array { return $this->rawMetadata; diff --git a/src/Helper/ClientHelper.php b/src/Helper/ClientHelper.php index 6b461b4..0f3c3a6 100644 --- a/src/Helper/ClientHelper.php +++ b/src/Helper/ClientHelper.php @@ -2,18 +2,17 @@ namespace MBO\RemoteGit\Helper; -use ReflectionClass; use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Exception\MissingConstException; use MBO\RemoteGit\Exception\RequiredParameterException; /** - * Helper to inspect client classes + * Helper to inspect client classes. */ class ClientHelper { /** - * Retrieve TYPE and TOKEN_TYPE from client class + * Retrieve TYPE and TOKEN_TYPE from client class. * * @param class-string $className * @@ -21,7 +20,7 @@ class ClientHelper */ public static function getStaticProperties(string $className): array { - $reflectionClass = new ReflectionClass($className); + $reflectionClass = new \ReflectionClass($className); if (!$reflectionClass->implementsInterface(ClientInterface::class)) { throw new RequiredParameterException(sprintf('%s must implement %s', $className, ClientInterface::class)); } diff --git a/src/Helper/LoggerHelper.php b/src/Helper/LoggerHelper.php index e63d468..d49cc19 100644 --- a/src/Helper/LoggerHelper.php +++ b/src/Helper/LoggerHelper.php @@ -6,12 +6,12 @@ use Psr\Log\NullLogger; /** - * Helper class to simplify NullLogger management + * Helper class to simplify NullLogger management. */ class LoggerHelper { /** - * Converts null to NullLogger + * Converts null to NullLogger. */ public static function handleNull( LoggerInterface $logger = null diff --git a/src/Http/TokenType.php b/src/Http/TokenType.php index 69934ca..47769fd 100644 --- a/src/Http/TokenType.php +++ b/src/Http/TokenType.php @@ -3,7 +3,7 @@ namespace MBO\RemoteGit\Http; /** - * Provides types of implementation for token + * Provides types of implementation for token. */ class TokenType { @@ -12,7 +12,7 @@ class TokenType public const AUTHORIZATION_TOKEN = 'Authorization: token {token}'; /** - * Create HTTP headers according to a tokenType + * Create HTTP headers according to a tokenType. * * @return array */ diff --git a/src/Local/LocalClient.php b/src/Local/LocalClient.php index 07066e8..826dfef 100644 --- a/src/Local/LocalClient.php +++ b/src/Local/LocalClient.php @@ -2,16 +2,16 @@ namespace MBO\RemoteGit\Local; -use Psr\Log\LoggerInterface; use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Exception\RawFileNotFoundException; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Helper\LoggerHelper; use MBO\RemoteGit\Http\TokenType; use MBO\RemoteGit\ProjectInterface; +use Psr\Log\LoggerInterface; /** - * Client for a local folder containing a project hierarchy + * Client for a local folder containing a project hierarchy. */ class LocalClient implements ClientInterface { @@ -19,7 +19,7 @@ class LocalClient implements ClientInterface public const TOKEN_TYPE = TokenType::NONE; /** - * Path to the root folder + * Path to the root folder. * * @var string */ @@ -31,7 +31,7 @@ class LocalClient implements ClientInterface private $logger; /** - * Create a LocalClient for a folder containing a hierarchy of git repositories + * Create a LocalClient for a folder containing a hierarchy of git repositories. * * @SuppressWarnings(PHPMD.StaticAccess) */ @@ -41,9 +41,6 @@ public function __construct(string $rootPath, LoggerInterface $logger = null) $this->logger = LoggerHelper::handleNull($logger); } - /** - * {@inheritDoc} - */ public function find(FindOptions $options): array { $projects = []; @@ -62,7 +59,7 @@ public function find(FindOptions $options): array } /** - * Create a LocalProject retreiving metadata from absolute path to project + * Create a LocalProject retreiving metadata from absolute path to project. * * @param string $projectFolder * @@ -128,9 +125,6 @@ protected function findProjectFolders(string $parentPath, array &$projectFolders } } - /** - * {@inheritDoc} - */ public function getRawFile( ProjectInterface $project, string $filePath, diff --git a/src/Local/LocalProject.php b/src/Local/LocalProject.php index 37065f8..29574eb 100644 --- a/src/Local/LocalProject.php +++ b/src/Local/LocalProject.php @@ -5,7 +5,7 @@ use MBO\RemoteGit\ProjectInterface; /** - * Project corresponding to a local git folder + * Project corresponding to a local git folder. */ class LocalProject implements ProjectInterface { @@ -16,41 +16,26 @@ public function __construct(private array $rawMetadata) { } - /** - * {@inheritDoc} - */ public function getId(): string { return $this->rawMetadata['id']; } - /** - * {@inheritDoc} - */ public function getName(): string { return $this->rawMetadata['full_name']; } - /** - * {@inheritDoc} - */ public function getDefaultBranch(): ?string { return $this->rawMetadata['head_branch']; } - /** - * {@inheritDoc} - */ public function getHttpUrl(): string { return $this->rawMetadata['full_path']; } - /** - * {@inheritDoc} - */ public function getRawMetadata(): array { return $this->rawMetadata; diff --git a/src/ProjectFilterInterface.php b/src/ProjectFilterInterface.php index fd2a383..0bc5af6 100644 --- a/src/ProjectFilterInterface.php +++ b/src/ProjectFilterInterface.php @@ -3,19 +3,19 @@ namespace MBO\RemoteGit; /** - * Test if a project should be included in satis config (regexp, ) + * Test if a project should be included in satis config (regexp, ). * * @author mborne */ interface ProjectFilterInterface { /** - * Get filter description (ex : "Project should contains a composer.json file") + * Get filter description (ex : "Project should contains a composer.json file"). */ public function getDescription(): string; /** - * Returns true if the project should be included in satis configuration + * Returns true if the project should be included in satis configuration. */ public function isAccepted(ProjectInterface $project): bool; } diff --git a/src/ProjectInterface.php b/src/ProjectInterface.php index da0e5d5..11f9181 100644 --- a/src/ProjectInterface.php +++ b/src/ProjectInterface.php @@ -3,34 +3,34 @@ namespace MBO\RemoteGit; /** - * Common project properties between different git project host (gitlab, github, etc.) + * Common project properties between different git project host (gitlab, github, etc.). * * @author mborne */ interface ProjectInterface { /** - * Get project id + * Get project id. */ public function getId(): string; /** - * Get project name (with namespace) + * Get project name (with namespace). */ public function getName(): string; /** - * Get default branch + * Get default branch. */ public function getDefaultBranch(): ?string; /** - * Get http url + * Get http url. */ public function getHttpUrl(): string; /** - * Get hosting service specific properties + * Get hosting service specific properties. * * @return array */ diff --git a/tests/Filter/ComposerProjectFilterTest.php b/tests/Filter/ComposerProjectFilterTest.php index 35cdf87..e54a102 100644 --- a/tests/Filter/ComposerProjectFilterTest.php +++ b/tests/Filter/ComposerProjectFilterTest.php @@ -2,17 +2,17 @@ namespace MBO\RemoteGit\Tests\Filter; -use MBO\RemoteGit\Tests\TestCase; use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Filter\ComposerProjectFilter; +use MBO\RemoteGit\Tests\TestCase; /** - * Test ComposerProjectFilter + * Test ComposerProjectFilter. */ class ComposerProjectFilterTest extends TestCase { /** - * Test getDescription + * Test getDescription. */ public function testGetDescription(): void { @@ -33,7 +33,7 @@ public function testGetDescription(): void } /** - * Rejected if composer.json doesn't exists + * Rejected if composer.json doesn't exists. */ public function testMissingComposerJson(): void { @@ -53,7 +53,7 @@ public function testMissingComposerJson(): void } /** - * Accepted if composer.json exists + * Accepted if composer.json exists. */ public function testComposerJsonAndTypeFilter(): void { @@ -86,7 +86,7 @@ public function testComposerJsonAndTypeFilter(): void } /** - * Accepted if composer.json exists + * Accepted if composer.json exists. */ public function testComposerJsonAndMultipleTypeFilter(): void { diff --git a/tests/Filter/FilterCollectionTest.php b/tests/Filter/FilterCollectionTest.php index efa08f6..5d6f988 100644 --- a/tests/Filter/FilterCollectionTest.php +++ b/tests/Filter/FilterCollectionTest.php @@ -2,13 +2,13 @@ namespace MBO\RemoteGit\Tests\Filter; +use MBO\RemoteGit\Filter\FilterCollection; +use MBO\RemoteGit\ProjectFilterInterface; use MBO\RemoteGit\Tests\TestCase; use Psr\Log\NullLogger; -use MBO\RemoteGit\ProjectFilterInterface; -use MBO\RemoteGit\Filter\FilterCollection; /** - * Test FilterCollection + * Test FilterCollection. */ class FilterCollectionTest extends TestCase { @@ -20,7 +20,7 @@ public function testEmpty(): void } /** - * Create a fake ProjectFilterInterface returning true or false + * Create a fake ProjectFilterInterface returning true or false. * * @return ProjectFilterInterface */ @@ -58,7 +58,7 @@ public function testOneFalse(): void } /** - * Check that isAccepted is unanymous + * Check that isAccepted is unanymous. */ public function testTrueFalseTrue(): void { diff --git a/tests/Filter/IgnoreRegexpFilterTest.php b/tests/Filter/IgnoreRegexpFilterTest.php index a6cb4ed..5adf839 100644 --- a/tests/Filter/IgnoreRegexpFilterTest.php +++ b/tests/Filter/IgnoreRegexpFilterTest.php @@ -2,11 +2,11 @@ namespace MBO\RemoteGit\Tests\Filter; -use MBO\RemoteGit\Tests\TestCase; use MBO\RemoteGit\Filter\IgnoreRegexpFilter; +use MBO\RemoteGit\Tests\TestCase; /** - * Test IgnoreRegexpFilter + * Test IgnoreRegexpFilter. */ class IgnoreRegexpFilterTest extends TestCase { diff --git a/tests/Filter/RequiredFileFilterTest.php b/tests/Filter/RequiredFileFilterTest.php index 36cf01d..f2ba63b 100644 --- a/tests/Filter/RequiredFileFilterTest.php +++ b/tests/Filter/RequiredFileFilterTest.php @@ -2,17 +2,17 @@ namespace MBO\RemoteGit\Tests\Filter; -use MBO\RemoteGit\Tests\TestCase; use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Filter\RequiredFileFilter; +use MBO\RemoteGit\Tests\TestCase; /** - * Test RequiredFileFilter + * Test RequiredFileFilter. */ class RequiredFileFilterTest extends TestCase { /** - * Rejected if composer.json doesn't exists + * Rejected if composer.json doesn't exists. */ public function testRequiredFileMissing(): void { @@ -32,7 +32,7 @@ public function testRequiredFileMissing(): void } /** - * Accepted if composer.json exists + * Accepted if composer.json exists. */ public function testRequiredFilePresent(): void { diff --git a/tests/GithubClientTest.php b/tests/GithubClientTest.php index 49ceac7..a018a8f 100644 --- a/tests/GithubClientTest.php +++ b/tests/GithubClientTest.php @@ -2,12 +2,12 @@ namespace MBO\RemoteGit\Tests; -use Psr\Log\NullLogger; -use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\ClientFactory; +use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Github\GithubClient; use MBO\RemoteGit\Github\GithubProject; +use Psr\Log\NullLogger; class GithubClientTest extends TestCase { @@ -38,7 +38,7 @@ protected function createGithubClient(): GithubClient } /** - * Ensure client can find mborne's projects + * Ensure client can find mborne's projects. */ public function testUserAndOrgsRepositories(): void { @@ -91,7 +91,7 @@ public function testUserAndOrgsRepositories(): void } /** - * Ensure client can find mborne's projects with composer.json file + * Ensure client can find mborne's projects with composer.json file. */ public function testFilterFile(): void { @@ -134,7 +134,7 @@ public function testFilterFile(): void } /** - * Ensure client can find mborne's projects using _me_ + * Ensure client can find mborne's projects using _me_. */ public function testFakeUserMe(): void { diff --git a/tests/GitlabClientTest.php b/tests/GitlabClientTest.php index c260c65..1336ef0 100644 --- a/tests/GitlabClientTest.php +++ b/tests/GitlabClientTest.php @@ -2,12 +2,12 @@ namespace MBO\RemoteGit\Tests; -use Psr\Log\NullLogger; -use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\ClientFactory; +use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Gitlab\GitlabClient; use MBO\RemoteGit\Gitlab\GitlabProject; +use Psr\Log\NullLogger; class GitlabClientTest extends TestCase { @@ -38,7 +38,7 @@ protected function createGitlabClient(): GitlabClient } /** - * Ensure client can find mborne/sample-composer by username + * Ensure client can find mborne/sample-composer by username. */ public function testGitlabDotComByUser(): void { @@ -96,7 +96,7 @@ public function testGitlabDotComOrgs(): void } /** - * Ensure client can find mborne/sample-composer with search + * Ensure client can find mborne/sample-composer with search. */ public function testGitlabDotComSearch(): void { diff --git a/tests/GogsClientTest.php b/tests/GogsClientTest.php index 9363456..ebc6363 100644 --- a/tests/GogsClientTest.php +++ b/tests/GogsClientTest.php @@ -2,8 +2,8 @@ namespace MBO\RemoteGit\Tests; -use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\ClientFactory; +use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Gogs\GogsClient; use MBO\RemoteGit\Gogs\GogsProject; @@ -40,7 +40,7 @@ protected function createGitClient(): GogsClient } /** - * Test find by current user + * Test find by current user. */ public function testFindByCurrentUser(): void { @@ -83,7 +83,7 @@ public function testFindByCurrentUser(): void } /** - * Ensure client can find projects by username and organizations + * Ensure client can find projects by username and organizations. */ public function testFindByUserAndOrgs(): void { diff --git a/tests/Http/TokenTypeTest.php b/tests/Http/TokenTypeTest.php index 6ff25a4..1417937 100644 --- a/tests/Http/TokenTypeTest.php +++ b/tests/Http/TokenTypeTest.php @@ -2,8 +2,8 @@ namespace MBO\RemoteGit\Tests\Http; -use MBO\RemoteGit\Tests\TestCase; use MBO\RemoteGit\Http\TokenType; +use MBO\RemoteGit\Tests\TestCase; class TokenTypeTest extends TestCase { diff --git a/tests/LocalClientTest.php b/tests/LocalClientTest.php index e0d6649..24e971a 100644 --- a/tests/LocalClientTest.php +++ b/tests/LocalClientTest.php @@ -2,12 +2,12 @@ namespace MBO\RemoteGit\Tests; -use Psr\Log\NullLogger; -use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\ClientFactory; +use MBO\RemoteGit\ClientOptions; use MBO\RemoteGit\FindOptions; use MBO\RemoteGit\Local\LocalClient; use MBO\RemoteGit\Local\LocalProject; +use Psr\Log\NullLogger; use Symfony\Component\Filesystem\Filesystem; class LocalClientTest extends TestCase @@ -15,7 +15,7 @@ class LocalClientTest extends TestCase public const TEMP_DIR = '/tmp/remote-git-test'; /** - * Clone some projects in /tmp/remote-git-test to perform functional tests + * Clone some projects in /tmp/remote-git-test to perform functional tests. */ public static function setUpBeforeClass(): void { @@ -32,7 +32,7 @@ public static function setUpBeforeClass(): void } /** - * Create a LocalClient for sample test directory + * Create a LocalClient for sample test directory. */ protected function createLocalClient(): LocalClient { @@ -53,7 +53,7 @@ protected function createLocalClient(): LocalClient } /** - * Find all projects in test folder + * Find all projects in test folder. * * @return LocalProject[] */ @@ -77,7 +77,7 @@ protected function findAllProjects(): array } /** - * Ensure that mborne/remote-git and mborne/satis-gitlab are found + * Ensure that mborne/remote-git and mborne/satis-gitlab are found. */ public function testFindAll(): void { @@ -90,7 +90,7 @@ public function testFindAll(): void } /** - * Check that raw file content can be retreived from non bare repository + * Check that raw file content can be retreived from non bare repository. */ public function testGetRawFileFromNonBareRepository(): void { @@ -107,7 +107,7 @@ public function testGetRawFileFromNonBareRepository(): void } /** - * Check that raw file content can be retreived from bare repository + * Check that raw file content can be retreived from bare repository. */ public function testGetRawFileFromBareRepository(): void { diff --git a/tests/TestCase.php b/tests/TestCase.php index c2b48e2..7607b9d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,16 +2,15 @@ namespace MBO\RemoteGit\Tests; -use Exception; use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Exception\RawFileNotFoundException; -use PHPUnit\Framework\TestCase as BaseTestCase; use MBO\RemoteGit\ProjectInterface; +use PHPUnit\Framework\TestCase as BaseTestCase; class TestCase extends BaseTestCase { /** - * Create a fake project with a given name + * Create a fake project with a given name. * * @return ProjectInterface */ @@ -33,7 +32,7 @@ protected function createMockProject(string $projectName) } /** - * Ensure that getter works for project + * Ensure that getter works for project. */ protected function assertGettersWorks(ProjectInterface $project): void { @@ -59,7 +58,7 @@ protected function ensureThatRawFileNotFoundThrowsException( $thrown = null; try { $client->getRawFile($project, 'NOT-FOUND.md', $defaultBranch); - } catch (Exception $e) { + } catch (\Exception $e) { $thrown = $e; } $this->assertNotNull($thrown); From 07b320bb90def61c373ff4484f3a949428842a1c Mon Sep 17 00:00:00 2001 From: mborne Date: Sat, 16 Mar 2024 10:43:20 +0100 Subject: [PATCH 7/8] fix(php-cs-fixer): allow global_namespace_import conflicting with phpstan --- Makefile | 6 +++--- src/Helper/ClientHelper.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 87430eb..5c2e664 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PHP_CS_RULES=@Symfony +PHP_CS_RULES=@Symfony,-global_namespace_import PHP_MD_RULES=cleancode,codesize,controversial,design,naming,unusedcode .PHONY: test @@ -29,8 +29,8 @@ fix-style: vendor .PHONY: check-style check-style: vendor @echo "-- Checking coding style using php-cs-fixer (run 'make fix-style' if it fails)" - vendor/bin/php-cs-fixer fix src --rules $(PHP_CS_RULES) -v --dry-run --diff --using-cache=no - vendor/bin/php-cs-fixer fix tests --rules $(PHP_CS_RULES) -v --dry-run --diff --using-cache=no + vendor/bin/php-cs-fixer fix src --rules $(PHP_CS_RULES) -v --dry-run --diff + vendor/bin/php-cs-fixer fix tests --rules $(PHP_CS_RULES) -v --dry-run --diff vendor: composer install diff --git a/src/Helper/ClientHelper.php b/src/Helper/ClientHelper.php index 0f3c3a6..2aa3a4e 100644 --- a/src/Helper/ClientHelper.php +++ b/src/Helper/ClientHelper.php @@ -5,6 +5,7 @@ use MBO\RemoteGit\ClientInterface; use MBO\RemoteGit\Exception\MissingConstException; use MBO\RemoteGit\Exception\RequiredParameterException; +use ReflectionClass; /** * Helper to inspect client classes. @@ -20,7 +21,7 @@ class ClientHelper */ public static function getStaticProperties(string $className): array { - $reflectionClass = new \ReflectionClass($className); + $reflectionClass = new ReflectionClass($className); if (!$reflectionClass->implementsInterface(ClientInterface::class)) { throw new RequiredParameterException(sprintf('%s must implement %s', $className, ClientInterface::class)); } From e7107bd7830442c235e6ebe0bb4fd3903a28e675 Mon Sep 17 00:00:00 2001 From: mborne Date: Sat, 16 Mar 2024 10:48:28 +0100 Subject: [PATCH 8/8] chore(composer): require php >= 8.1 (refs #25) --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 1c7ce97..e404e12 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ } }, "require": { + "php": ">=8.1", "guzzlehttp/guzzle": "~7.0" }, "require-dev": {