Skip to content
Closed
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
27 changes: 22 additions & 5 deletions packages/core/src/Kernel/LoadDiscoveryClasses.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Tempest\Core\Kernel;

use Exception;
use Tempest\Container\Container;
use Tempest\Core\DiscoveryCache;
use Tempest\Core\DiscoveryCacheStrategy;
Expand Down Expand Up @@ -198,11 +199,27 @@ private function scan(DiscoveryLocation $location, array $discoveries, string $p
// Resolve `#[SkipDiscovery]` for this class
$skipDiscovery = $input->getAttribute(SkipDiscovery::class);

if ($skipDiscovery !== null && $skipDiscovery->except === []) {
$this->shouldSkipForClass[$className] = true;
} elseif ($skipDiscovery !== null) {
foreach ($skipDiscovery->except as $except) {
$this->shouldSkipForClass[$className][$except] = true;
if ($skipDiscovery !== null) {
$when = false;
// Evaluate conditional skip
if ($skipDiscovery->when !== null) {
try {
$when = (bool) $this->container->invoke($skipDiscovery->when);
} catch (Throwable $throw) {
throw new Exception($throw->getMessage(), 0, $throw);
}
}

$shouldApply = $skipDiscovery->when === null || $when;

if ($shouldApply) {
if ($skipDiscovery->except === []) {
$this->shouldSkipForClass[$className] = true;
} else {
foreach ($skipDiscovery->except as $except) {
$this->shouldSkipForClass[$className][$except] = true;
}
}
}
}

Expand Down
5 changes: 4 additions & 1 deletion packages/discovery/src/SkipDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tempest\Discovery;

use Attribute;
use Closure;

/**
* Instruct Tempest to not discover this class.
Expand All @@ -15,8 +16,10 @@
public function __construct(
/**
* Allows the specified `Discovery` classes to still discover this class.
* @var array<class-string<\Tempest\Discovery\Discovery>>
* @param array<class-string<\Tempest\Discovery\Discovery>>
* @param Closure|null
*/
public array $except = [],
public ?Closure $when = null,
) {}
}
26 changes: 26 additions & 0 deletions tests/Fixtures/Discovery/ConditionallyHiddenDatabaseMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tests\Tempest\Fixtures\Discovery;

use Symfony\Component\Console\Application;
use Tempest\Console\ConsoleApplication;
use Tempest\Database\MigratesUp;
use Tempest\Database\QueryStatement;
use Tempest\Database\QueryStatements\CreateTableStatement;
use Tempest\Discovery\SkipDiscovery;

#[SkipDiscovery(when: static function (Application $application): bool {
return ! $application instanceof ConsoleApplication;

Check failure on line 15 in tests/Fixtures/Discovery/ConditionallyHiddenDatabaseMigration.php

View workflow job for this annotation

GitHub Actions / Run static analysis: PHPStan

Instanceof between Symfony\Component\Console\Application and Tempest\Console\ConsoleApplication will always evaluate to false.
})]
final class ConditionallyHiddenDatabaseMigration implements MigratesUp
{
private(set) string $name = 'conditionally-hidden-migration';

public function up(): QueryStatement
{
return new CreateTableStatement('hidden')
->primary();
}
}
8 changes: 8 additions & 0 deletions tests/Integration/Core/LoadDiscoveryClassesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Tempest\Database\Migrations\RunnableMigrations;
use Tempest\Discovery\DiscoveryLocation;
use Tempest\Support\Arr;
use Tests\Tempest\Fixtures\Discovery\ConditionallyHiddenDatabaseMigration;
use Tests\Tempest\Fixtures\Discovery\HiddenDatabaseMigration;
use Tests\Tempest\Fixtures\Discovery\HiddenMigratableDatabaseMigration;
use Tests\Tempest\Fixtures\GlobalHiddenDiscovery;
Expand Down Expand Up @@ -81,4 +82,11 @@ public function only_load_specific_discovery_classes(): void

$this->assertTrue($dependency->discovered);
}

#[Test]
public function does_not_load_conditionally_hidden_classes(): void
{
$migrations = $this->container->get(RunnableMigrations::class);
$this->assertFalse(Arr\contains($migrations, fn ($m) => $m instanceof ConditionallyHiddenDatabaseMigration));
}
}
Loading