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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The package provides a PHP configuration API for PHPStan. Add this
to your `phpstan.php` file:

```php
# phpstan.php
// phpstan.php

use EliasHaeussler\PHPStanConfig;

Expand Down Expand Up @@ -110,18 +110,22 @@ $config->treatPhpDocTypesAsCertain();
$config->useCustomRule('ignoreAnnotationWithoutErrorIdentifier', false);

// Include Doctrine set
$config->createSet(PHPStanConfig\Set\DoctrineSet::class)
->withObjectManagerLoader('tests/object-manager.php')
->withOrmRepositoryClass(\MyApp\Doctrine\BetterEntityRepository::class)
->withOdmRepositoryClass(\MyApp\Doctrine\BetterDocumentRepository::class)
;
$config->createSet(
static function (PHPStanConfig\Set\DoctrineSet $set): void {
$set->withObjectManagerLoader('tests/object-manager.php');
$set->withOrmRepositoryClass(\MyApp\Doctrine\BetterEntityRepository::class);
$set->withOdmRepositoryClass(\MyApp\Doctrine\BetterDocumentRepository::class);
},
);

// Include Symfony set
$config->createSet(PHPStanConfig\Set\SymfonySet::class)
->withConsoleApplicationLoader('tests/build/console-application.php')
->withContainerXmlPath('var/cache/test-container.xml')
->disableConstantHassers()
;
$config->createSet(
static function (PHPStanConfig\Set\SymfonySet $set): void {
$set->withConsoleApplicationLoader('tests/build/console-application.php');
$set->withContainerXmlPath('var/cache/test-container.xml');
$set->disableConstantHassers();
},
);

// Include TYPO3 set
$typo3Set = PHPStanConfig\Set\TYPO3Set::create()
Expand Down
36 changes: 32 additions & 4 deletions src/Config/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@

namespace EliasHaeussler\PHPStanConfig\Config;

use Closure;
use EliasHaeussler\PHPStanConfig\Enums;
use EliasHaeussler\PHPStanConfig\Exception;
use EliasHaeussler\PHPStanConfig\Resource;
use EliasHaeussler\PHPStanConfig\Set;
use ReflectionFunction;
use ReflectionNamedType;

use function array_map;
use function is_a;
use function preg_quote;
use function sprintf;
use function str_starts_with;
Expand Down Expand Up @@ -70,21 +74,45 @@ public static function create(string $projectDirectory): self
/**
* @template T of Set\Set
*
* @param class-string<T> $className
* @param Closure(T, self): void|class-string<T> $configuratorOrClassName
*
* @return T
* @throws Exception\SetConfiguratorIsNotValid
*/
public function createSet(string $className): Set\Set
public function createSet(Closure|string $configuratorOrClassName): self
{
if ($configuratorOrClassName instanceof Closure) {
$reflection = new ReflectionFunction($configuratorOrClassName);
$type = $reflection->getParameters()[0]->getType();

if (!($type instanceof ReflectionNamedType)) {
throw new Exception\SetConfiguratorIsNotValid();
}

$className = $type->getName();
$configurator = $configuratorOrClassName;
} else {
$className = $configuratorOrClassName;
$configurator = null;
}

if (!is_a($className, Set\Set::class, true)) {
throw new Exception\SetConfiguratorIsNotValid();
}

/** @var T $set */
$set = $className::create();

if ($set instanceof Set\PathAwareSet) {
$set->setProjectPath($this->projectPath);
}

if (null !== $configurator) {
$configurator($set, $this);
}

$this->withSets($set);

return $set;
return $this;
}

public function withSets(Set\Set ...$sets): self
Expand Down
41 changes: 41 additions & 0 deletions src/Exception/SetConfiguratorIsNotValid.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Composer package "eliashaeussler/phpstan-config".
*
* Copyright (C) 2023-2025 Elias Häußler <elias@haeussler.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace EliasHaeussler\PHPStanConfig\Exception;

/**
* SetConfiguratorIsNotValid.
*
* @author Elias Häußler <elias@haeussler.dev>
* @license GPL-3.0-or-later
*/
final class SetConfiguratorIsNotValid extends Exception
{
public function __construct()
{
parent::__construct(
'The given set configurator does not properly define the required set as first parameter.',
1763631052,
);
}
}
36 changes: 31 additions & 5 deletions tests/unit/Config/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,46 @@ protected function setUp(): void
$this->subject = Src\Config\Config::create('/my-project');
}

#[Framework\Attributes\Test]
public function createSetCreatesAndReturnsGivenSetByClassName(): void
{
$this->subject->createSet(Tests\Fixtures\DummySet::class);

self::assertSame(
[
'includes' => [],
'parameters' => [
'foo' => 'baz',
],
],
$this->subject->toArray(),
);
}

#[Framework\Attributes\Test]
public function createSetInitializesAndReturnsGivenSet(): void
{
$expected = Tests\Fixtures\DummySet::create();
$expected->setProjectPath(new Src\Resource\Path('/my-project'));
$validated = false;

$this->subject->createSet(
static function (Tests\Fixtures\DummySet $set) use (&$validated) {
$validated = true;

$actual = $this->subject->createSet(Tests\Fixtures\DummySet::class);
$expected = Tests\Fixtures\DummySet::create();
$expected->setProjectPath(new Src\Resource\Path('/my-project'));

self::assertEquals($expected, $actual);
self::assertEquals($expected, $set);

$set->parameters = ['baz' => 'foo'];
},
);

self::assertTrue($validated);
self::assertSame(
[
'includes' => [],
'parameters' => [
'foo' => 'baz',
'baz' => 'foo',
],
],
$this->subject->toArray(),
Expand Down