Skip to content

Commit 234632e

Browse files
committed
typos
1 parent 67acb19 commit 234632e

6 files changed

Lines changed: 131 additions & 94 deletions

File tree

README.md

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ This is the recommended pattern for packages and applications. It separates work
550550
```php
551551
use Chevere\Workflow\ProviderDiscovery;
552552

553-
$discovery = new ProviderDiscovery('/path/to/src');
553+
$discovery = ProviderDiscovery::fromDirectory('/path/to/src');
554554

555555
// `workflow()` providers e.g. [OrderWorkflow::class, UserWorkflow::class, ...]
556556
$workflowProviders = $discovery->providers();
@@ -559,18 +559,12 @@ $workflowProviders = $discovery->providers();
559559
$workflowDependencies = $discovery->dependencies();
560560
```
561561

562-
### Building Cache Files
562+
### Build discovery results
563563

564-
Call `build()` to persist the discovery results as PHP return files. Subsequent bootstraps can load these files instead of re-scanning the directory on every request.
564+
Call `build()` to persist the discovery results as PHP return files, which you can commit to your repository or load at runtime for faster access without needing to scan directories:
565565

566566
```php
567-
$discovery = new ProviderDiscovery('/path/to/src');
568-
569-
// Write cache to the same directory
570-
$discovery->build();
571-
572-
// Or write to a separate cache directory
573-
$discovery->build('/path/to/cache');
567+
$discovery->build('/path/to/build');
574568
```
575569

576570
Two files are written:
@@ -580,29 +574,25 @@ Two files are written:
580574
| `workflow-providers.php` | `array<class-string<WorkflowProviderInterface>>` providers |
581575
| `workflow-dependencies.php` | `array<class-string>` required by discovered job actions |
582576

583-
### Working with chevere/container
584-
585-
If you use `chevere/container` for dependency injection, the discovery results can be used to automatically register dependencies in the container:
577+
Call `fromBuild()` to load the discovery results from the cache files:
586578

587579
```php
588-
use Chevere\Container\Dependencies;
589-
590-
$dependencies = new Dependencies(
591-
...$workflowProviders,
592-
...$workflowDependencies
593-
);
594-
$container = $container->withAutoInject($dependencies);
580+
$discovery = ProviderDiscovery::fromBuild('/path/to/build');
595581
```
596582

597-
To validate that your container can satisfy all discovered dependencies before running any workflow, call `assert()`:
583+
### Validating Dependencies
584+
585+
To validate that your container can satisfy all discovered dependencies before running any workflow, call `assert()` on `Dependencies` with your container instance. It will throw if any required class is missing:
598586

599587
```php
588+
$dependencies = new Dependencies(
589+
...$discovery->dependencies(),
590+
...$discovery->providers()
591+
);
600592
$dependencies->assert($container);
601593
```
602594

603-
### Working with any PSR-11 container
604-
605-
Use the discovered dependency list to assert that your PSR-11 container can satisfy every dependency before running any workflow:
595+
You can also manually check the list of dependencies against your PSR-11 container:
606596

607597
```php
608598
use Chevere\Workflow\ProviderDiscovery;
@@ -636,6 +626,7 @@ $container = new Container(
636626
);
637627

638628
// Run workflow with container
629+
// The system will auto-inject and assert dependencies.
639630
$result = run($workflow, $container, ...$vars);
640631
```
641632

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"chevere/filesystem": "^2.0",
2222
"chevere/parameter": "^2.0.5",
2323
"chevere/regex": "^1.0.2",
24-
"spatie/php-structure-discoverer": "^2.4"
24+
"spatie/php-structure-discoverer": "^2.3.2||^2.4"
2525
},
2626
"require-dev": {
2727
"opis/json-schema": "^2.6",

src/Interfaces/ProviderDiscoveryInterface.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@
1313

1414
namespace Chevere\Workflow\Interfaces;
1515

16+
use RuntimeException;
17+
1618
/**
1719
* Describes the component in charge of discovering workflow providers and their dependencies.
1820
*/
1921
interface ProviderDiscoveryInterface
2022
{
23+
public const PROVIDERS_FILENAME = 'workflow-providers.php';
24+
25+
public const DEPENDENCIES_FILENAME = 'workflow-dependencies.php';
26+
2127
/**
2228
* @return array<class-string<WorkflowProviderInterface>> List of provider class names.
2329
*/
@@ -34,7 +40,23 @@ public function dependencies(): array;
3440
* - `workflow-providers.php`: Array of discovered provider class names.
3541
* - `workflow-dependencies.php`: Array of dependency class names required by jobs.
3642
*
37-
* @param string|null $dir If null, store files in the same directory specified for discovery lookup.
43+
* @param string $dir Directory where the discovery results will be stored.
44+
*/
45+
public function build(string $dir): void;
46+
47+
/**
48+
* Creates a ProviderDiscovery instance by scanning the specified directory for workflow providers.
49+
*
50+
* @param string $dir Directory to scan for workflow providers.
51+
* @throws RuntimeException If the directory cannot be read or is invalid.
52+
*/
53+
public static function fromDirectory(string $dir): self;
54+
55+
/**
56+
* Creates a ProviderDiscovery instance by loading discovery results from the specified cache directory.
57+
*
58+
* @param string $dir Directory where the discovery cache files are located.
59+
* @throws RuntimeException If the cache files cannot be read or are invalid.
3860
*/
39-
public function build(?string $dir = null): void;
61+
public static function fromBuild(string $dir): self;
4062
}

src/ProviderDiscovery.php

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,13 @@
2525
final class ProviderDiscovery implements ProviderDiscoveryInterface
2626
{
2727
/**
28-
* @var array<class-string<WorkflowProviderInterface>>
28+
* @param array<class-string<WorkflowProviderInterface>> $providers
29+
* @param array<class-string> $dependencies
2930
*/
30-
private array $providers = [];
31-
32-
/**
33-
* @var array<class-string>
34-
*/
35-
private array $dependencies = [];
36-
37-
private DirectoryInterface $directory;
38-
39-
public function __construct(string $dir)
40-
{
41-
$this->directory = directoryForPath(
42-
realpath($dir)
43-
?: throw new RuntimeException(
44-
"Unable to resolve path for `{$dir}`"
45-
)
46-
);
47-
/** @var array<class-string<WorkflowProviderInterface>> $discovered */
48-
$discovered = Discover::in($this->directory->path()->__toString())
49-
->classes()->implementing(WorkflowProviderInterface::class)->get();
50-
sort($discovered);
51-
$this->providers = $discovered;
52-
$deps = [];
53-
foreach ($this->providers as $providerClass) {
54-
foreach ($providerClass::workflow()->dependencies()->classes() as $dependencyClass) {
55-
$deps[$dependencyClass] = true;
56-
}
57-
}
58-
/** @var array<class-string> $keys */
59-
$keys = array_keys($deps);
60-
sort($keys);
61-
$this->dependencies = $keys;
31+
public function __construct(
32+
public readonly array $providers,
33+
public readonly array $dependencies
34+
) {
6235
}
6336

6437
public function providers(): array
@@ -71,24 +44,66 @@ public function dependencies(): array
7144
return $this->dependencies;
7245
}
7346

74-
public function build(?string $dir = null): void
47+
public function build(string $dir): void
7548
{
76-
$directory = $this->directory;
77-
if ($dir !== null) {
78-
$directory = directoryForPath(
79-
realpath($dir)
80-
?: throw new RuntimeException(
81-
"Unable to resolve path for `{$dir}`"
82-
)
83-
);
84-
}
85-
filePhpReturnForPath($directory->path()->getChild('workflow-providers.php'))
49+
$directory = static::getDirectory($dir);
50+
filePhpReturnForPath(
51+
$directory->path()->getChild(static::PROVIDERS_FILENAME)
52+
)
8653
->put(
8754
new StorableVariable($this->providers)
8855
);
89-
filePhpReturnForPath($directory->path()->getChild('workflow-dependencies.php'))
56+
filePhpReturnForPath(
57+
$directory->path()->getChild(static::DEPENDENCIES_FILENAME)
58+
)
9059
->put(
9160
new StorableVariable($this->dependencies)
9261
);
9362
}
63+
64+
public static function fromDirectory(string $dir): ProviderDiscoveryInterface
65+
{
66+
$directory = static::getDirectory($dir);
67+
/** @var array<class-string<WorkflowProviderInterface>> $providers */
68+
$providers = Discover::in($directory->path()->__toString())
69+
->classes()->implementing(WorkflowProviderInterface::class)
70+
->get();
71+
sort($providers);
72+
$dependencies = [];
73+
foreach ($providers as $providerClass) {
74+
foreach ($providerClass::workflow()->dependencies()->classes() as $dependencyClass) {
75+
$dependencies[$dependencyClass] = true;
76+
}
77+
}
78+
/** @var array<class-string> $dependencies */
79+
$dependencies = array_keys($dependencies);
80+
sort($dependencies);
81+
82+
return new self($providers, $dependencies);
83+
}
84+
85+
public static function fromBuild(string $dir): ProviderDiscoveryInterface
86+
{
87+
$directory = static::getDirectory($dir);
88+
/** @var array<class-string<WorkflowProviderInterface>> $providers */
89+
$providers = filePhpReturnForPath(
90+
$directory->path()->getChild(static::PROVIDERS_FILENAME)
91+
)->get();
92+
/** @var array<class-string> $dependencies */
93+
$dependencies = filePhpReturnForPath(
94+
$directory->path()->getChild(static::DEPENDENCIES_FILENAME)
95+
)->get();
96+
97+
return new self($providers, $dependencies);
98+
}
99+
100+
private static function getDirectory(string $dir): DirectoryInterface
101+
{
102+
return directoryForPath(
103+
realpath($dir)
104+
?: throw new RuntimeException(
105+
"Unable to resolve path for `{$dir}`"
106+
)
107+
);
108+
}
94109
}

tests/ProviderDiscoveryTest.php

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ protected function tearDown(): void
4343
public function testInvalidPath(): void
4444
{
4545
$this->expectException(RuntimeException::class);
46-
new ProviderDiscovery('/non/existent/path/that/does/not/exist');
46+
ProviderDiscovery::fromDirectory('/non/existent/path/that/does/not/exist');
4747
}
4848

4949
public function testNoProviders(): void
5050
{
51-
$discovery = new ProviderDiscovery($this->tempDir);
51+
$discovery = ProviderDiscovery::fromDirectory($this->tempDir);
5252
$this->assertSame([], $discovery->providers());
5353
$this->assertSame([], $discovery->dependencies());
5454
}
5555

5656
public function testProviders(): void
5757
{
58-
$discovery = new ProviderDiscovery($this->fixtureDir);
58+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
5959
$this->assertSame(
6060
[
6161
TestProviderWithDependency::class,
@@ -67,7 +67,7 @@ public function testProviders(): void
6767

6868
public function testProvidersAreSorted(): void
6969
{
70-
$discovery = new ProviderDiscovery($this->fixtureDir);
70+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
7171
$providers = $discovery->providers();
7272
$sorted = $providers;
7373
sort($sorted);
@@ -76,7 +76,7 @@ public function testProvidersAreSorted(): void
7676

7777
public function testDependencies(): void
7878
{
79-
$discovery = new ProviderDiscovery($this->fixtureDir);
79+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
8080
$this->assertSame(
8181
[TestActionRequiresInterface::class],
8282
$discovery->dependencies()
@@ -85,27 +85,16 @@ public function testDependencies(): void
8585

8686
public function testDependenciesAreSorted(): void
8787
{
88-
$discovery = new ProviderDiscovery($this->fixtureDir);
88+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
8989
$dependencies = $discovery->dependencies();
9090
$sorted = $dependencies;
9191
sort($sorted);
9292
$this->assertSame($sorted, $dependencies);
9393
}
9494

95-
public function testBuildDefaultDir(): void
95+
public function testBuild(): void
9696
{
97-
$discovery = new ProviderDiscovery($this->tempDir);
98-
$discovery->build();
99-
$dir = directoryForPath($this->tempDir);
100-
$providers = filePhpReturnForPath($dir->path()->getChild('workflow-providers.php'))->get();
101-
$this->assertSame([], $providers);
102-
$dependencies = filePhpReturnForPath($dir->path()->getChild('workflow-dependencies.php'))->get();
103-
$this->assertSame([], $dependencies);
104-
}
105-
106-
public function testBuildExplicitDir(): void
107-
{
108-
$discovery = new ProviderDiscovery($this->fixtureDir);
97+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
10998
$discovery->build($this->tempDir);
11099
$dir = directoryForPath($this->tempDir);
111100
$providers = filePhpReturnForPath($dir->path()->getChild('workflow-providers.php'))->get();
@@ -116,8 +105,23 @@ public function testBuildExplicitDir(): void
116105

117106
public function testBuildInvalidDir(): void
118107
{
119-
$discovery = new ProviderDiscovery($this->tempDir);
108+
$discovery = ProviderDiscovery::fromDirectory($this->tempDir);
120109
$this->expectException(RuntimeException::class);
121110
$discovery->build('/non/existent/build/path');
122111
}
112+
113+
public function testFromBuild(): void
114+
{
115+
$discovery = ProviderDiscovery::fromDirectory($this->fixtureDir);
116+
$discovery->build($this->tempDir);
117+
$loaded = ProviderDiscovery::fromBuild($this->tempDir);
118+
$this->assertSame($discovery->providers(), $loaded->providers());
119+
$this->assertSame($discovery->dependencies(), $loaded->dependencies());
120+
}
121+
122+
public function testFromBuildInvalidDir(): void
123+
{
124+
$this->expectException(RuntimeException::class);
125+
ProviderDiscovery::fromBuild('/non/existent/build/path');
126+
}
123127
}

tests/RunnerTest.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,13 +614,18 @@ public function testActionVariadicNamedFooIsPreserved(): void
614614

615615
public function testRunnerActionClassNameWithDependency(): void
616616
{
617-
$this->expectNotToPerformAssertions();
618617
$workflow = workflow(
619618
job1: sync(TestActionDependsNoParams::class),
620619
);
621-
run($workflow);
622620
$container = new Container(dependency: new stdClass());
623621
run($workflow, $container);
622+
$this->expectException(LogicException::class);
623+
$this->expectExceptionMessage(
624+
<<<PLAIN
625+
Missing argument `dependency` as previously defined by `Chevere\Tests\src\TestActionDependsNoParams`
626+
PLAIN
627+
);
628+
run($workflow);
624629
}
625630

626631
public function testRunnerActionClassNameMissingDependency(): void

0 commit comments

Comments
 (0)