Skip to content

Commit e2cb52d

Browse files
authored
Add support for validators on service providers (#831)
* Add support for validators on service providers * Ignore unreleated phpstan
1 parent cf44711 commit e2cb52d

File tree

3 files changed

+91
-3
lines changed

3 files changed

+91
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Added `laravel/serializable-closure` as a dependency to `mantle-framework/support` to
1313
support serialization of closures.
14+
- Added support for `Mantle\Types\Validator` attributes on service providers to
15+
conditionally boot them based on custom logic.
1416
- Added `Mantle\Types\Attributes\Admin` and `Mantle\Types\Attributes\Request`
1517
validator attributes.
1618

src/mantle/support/class-service-provider.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Mantle\Console\Command;
1212
use Mantle\Contracts\Application;
1313
use Mantle\Support\Traits\Hookable;
14+
use Mantle\Types\Validator;
1415
use Psr\Log\{LoggerAwareInterface, LoggerAwareTrait};
1516
use Symfony\Component\Console\Command\Command as Symfony_Command;
1617

@@ -81,8 +82,10 @@ public function boot_provider(): void {
8182
$this->setLogger( $this->app['log']->driver() );
8283
}
8384

84-
$this->register_hooks();
85-
$this->boot();
85+
if ( $this->should_boot_provider() ) {
86+
$this->register_hooks();
87+
$this->boot();
88+
}
8689
}
8790

8891
/**
@@ -216,4 +219,27 @@ public static function paths_to_publish( array|string|null $providers = null, ar
216219
default => [],
217220
};
218221
}
222+
223+
/**
224+
* Determine if the provider should be booted.
225+
*
226+
* Checks for any Validator attributes on the class and runs them.
227+
*/
228+
protected function should_boot_provider(): bool {
229+
$validator = Reflector::get_attributes_for_class( $this, Validator::class, \ReflectionAttribute::IS_INSTANCEOF );
230+
231+
if ( empty( $validator ) ) {
232+
return true;
233+
}
234+
235+
foreach ( $validator as $attribute ) {
236+
$instance = $attribute->newInstance();
237+
238+
if ( ! $instance->validate() ) {
239+
return false;
240+
}
241+
}
242+
243+
return true;
244+
}
219245
}

tests/Support/ServiceProviderTest.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
<?php
22
namespace Mantle\Tests\Support;
33

4+
use Attribute;
45
use Mantle\Application\Application;
56
use Mantle\Console\Command;
67
use Mantle\Contracts\Providers as ProviderContracts;
78
use Mantle\Events\Dispatcher;
89
use Mantle\Support\Service_Provider;
910
use Mantle\Support\Attributes\Action;
1011
use Mantle\Support\Attributes\Filter;
12+
use Mantle\Types\Validator;
1113
use Mockery as m;
1214

1315
class ServiceProviderTest extends \Mockery\Adapter\Phpunit\MockeryTestCase {
@@ -276,6 +278,30 @@ function ( $resolved ) {
276278

277279
$this->assertEquals( 'one', $_SERVER['__after_resolving'] );
278280
}
281+
282+
public function test_service_provider_with_passing_validator(): void {
283+
$_SERVER['__service_provider_booted'] = false;
284+
285+
$app = m::mock( Application::class )->makePartial();
286+
287+
$app->register( PassingValidatorServiceProvider::class );
288+
289+
$this->assertFalse( $_SERVER['__service_provider_booted'] );
290+
$app->boot();
291+
$this->assertTrue( $_SERVER['__service_provider_booted'] );
292+
}
293+
294+
public function test_service_provider_with_failing_validator(): void {
295+
$_SERVER['__service_provider_booted'] = false;
296+
297+
$app = m::mock( Application::class )->makePartial();
298+
299+
$app->register( FailingValidatorServiceProvider::class );
300+
301+
$this->assertFalse( $_SERVER['__service_provider_booted'] );
302+
$app->boot();
303+
$this->assertFalse( $_SERVER['__service_provider_booted'] );
304+
}
279305
}
280306

281307
class Provider_Test_Hook extends Service_Provider {
@@ -331,6 +357,40 @@ public function boot() {
331357
}
332358
}
333359

334-
class Example_Service_Provider_Event {
360+
class Example_Service_Provider_Event {}
361+
362+
#[Attribute]
363+
class PassingValidator implements Validator {
364+
public function validate(): bool {
365+
return true;
366+
}
367+
}
368+
369+
#[PassingValidator]
370+
class PassingValidatorServiceProvider extends Service_Provider {
371+
public function register() {
372+
$_SERVER['__service_provider_registered'] = true;
373+
}
374+
375+
public function boot() {
376+
$_SERVER['__service_provider_booted'] = true;
377+
}
378+
}
335379

380+
#[Attribute]
381+
class FailingValidator implements Validator {
382+
public function validate(): bool {
383+
return false;
384+
}
385+
}
386+
387+
#[FailingValidator]
388+
class FailingValidatorServiceProvider extends Service_Provider {
389+
public function register() {
390+
$_SERVER['__service_provider_registered'] = true;
391+
}
392+
393+
public function boot() {
394+
$_SERVER['__service_provider_booted'] = true;
395+
}
336396
}

0 commit comments

Comments
 (0)