diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php index bec6645f5..02941c3c1 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php @@ -163,7 +163,7 @@ class FormSidebarWidget extends AdminWidget implements */ private $requiredGlobalAclPermissions = []; - private RevisionsManager $revisionManager; + private ?RevisionsManager $revisionManager; /** * @param array|ArrayInterface $data Class data. @@ -549,7 +549,7 @@ public function isObjRevisionable() $this->isObjRevisionable = false; } else { $obj = $this->form()->obj(); - if (!$obj->id()) { + if (!$obj->id() || $this->revisionManager === null) { $this->isObjRevisionable = false; return $this->isObjRevisionable; } @@ -903,6 +903,6 @@ protected function setDependencies(Container $container) { parent::setDependencies($container); - $this->revisionManager = $container['revisions/manager']; + $this->revisionManager = ($container['revisions/manager'] ?? null); } } diff --git a/packages/admin/tests/Charcoal/Admin/Action/LoginActionTest.php b/packages/admin/tests/Charcoal/Admin/Action/LoginActionTest.php index 8c814c806..0e0449d25 100644 --- a/packages/admin/tests/Charcoal/Admin/Action/LoginActionTest.php +++ b/packages/admin/tests/Charcoal/Admin/Action/LoginActionTest.php @@ -2,6 +2,7 @@ namespace Charcoal\Tests\Admin\Action; +use Charcoal\App\Facade\Facade; use PDO; use ReflectionClass; diff --git a/packages/admin/tests/Charcoal/Admin/ContainerProvider.php b/packages/admin/tests/Charcoal/Admin/ContainerProvider.php index dd0f8b434..05c4dda44 100644 --- a/packages/admin/tests/Charcoal/Admin/ContainerProvider.php +++ b/packages/admin/tests/Charcoal/Admin/ContainerProvider.php @@ -2,6 +2,7 @@ namespace Charcoal\Tests\Admin; +use Charcoal\App\Facade\Facade; use PDO; // From Mockery @@ -92,6 +93,9 @@ public function registerDebug(Container $container) */ public function registerBaseServices(Container $container) { + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); + $this->registerDebug($container); $this->registerConfig($container); $this->registerDatabase($container); @@ -390,6 +394,7 @@ public function registerCache(Container $container) public function registerEvent(Container $container) { $container['event/dispatcher'] = new EventDispatcher(); + $container['app/event/dispatcher'] = $container['event/dispatcher']; } /** @@ -554,6 +559,9 @@ public function registerEmailFactory(Container $container) */ public function registerActionDependencies(Container $container) { + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); + $this->registerDebug($container); $this->registerLogger($container); $this->registerDatabase($container); diff --git a/packages/app/src/Charcoal/App/Facade/Facade.php b/packages/app/src/Charcoal/App/Facade/Facade.php index af822aa26..196405442 100644 --- a/packages/app/src/Charcoal/App/Facade/Facade.php +++ b/packages/app/src/Charcoal/App/Facade/Facade.php @@ -12,13 +12,13 @@ */ abstract class Facade { - protected static ContainerInterface $resolver; + protected static \ArrayAccess $resolver; /** * @var array */ protected static array $resolvedInstances = []; - public static function setFacadeResolver(ContainerInterface $resolver) + public static function setFacadeResolver(\ArrayAccess $resolver) { static::$resolver = $resolver; } diff --git a/packages/cms/tests/Charcoal/Cms/ContainerIntegrationTrait.php b/packages/cms/tests/Charcoal/Cms/ContainerIntegrationTrait.php index 46ee1cedd..1880f36c9 100644 --- a/packages/cms/tests/Charcoal/Cms/ContainerIntegrationTrait.php +++ b/packages/cms/tests/Charcoal/Cms/ContainerIntegrationTrait.php @@ -6,6 +6,7 @@ use Charcoal\App\AppContainer as Container; // From 'charcoal-cms/tests' +use Charcoal\App\Facade\Facade; use Charcoal\Tests\Cms\ContainerProvider; /** @@ -109,5 +110,8 @@ private function setupContainer() $this->container = $container; $this->containerProvider = $provider; + + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); } } diff --git a/packages/core/tests/Charcoal/CoreContainerIntegrationTrait.php b/packages/core/tests/Charcoal/CoreContainerIntegrationTrait.php index 57ce03768..dd4c5b46d 100644 --- a/packages/core/tests/Charcoal/CoreContainerIntegrationTrait.php +++ b/packages/core/tests/Charcoal/CoreContainerIntegrationTrait.php @@ -3,6 +3,7 @@ namespace Charcoal\Tests; // From Pimple +use Charcoal\App\Facade\Facade; use Pimple\Container; // From 'charcoal-core/tests' @@ -68,5 +69,8 @@ private function setupContainer() $this->container = $container; $this->containerProvider = $provider; + + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); } } diff --git a/packages/core/tests/Charcoal/CoreContainerProvider.php b/packages/core/tests/Charcoal/CoreContainerProvider.php index 6de374c33..be057796d 100644 --- a/packages/core/tests/Charcoal/CoreContainerProvider.php +++ b/packages/core/tests/Charcoal/CoreContainerProvider.php @@ -2,6 +2,7 @@ namespace Charcoal\Tests; +use Charcoal\Event\ServiceProvider\EventServiceProvider; use PDO; // From PSR-3 @@ -52,6 +53,7 @@ public function registerBaseServices(Container $container) $this->registerSource($container); $this->registerLogger($container); $this->registerCache($container); + $container->register(new EventServiceProvider()); } /** diff --git a/packages/core/tests/Charcoal/Mock/BadStorableMock.php b/packages/core/tests/Charcoal/Mock/BadStorableMock.php index 40765d358..5cd154c1e 100644 --- a/packages/core/tests/Charcoal/Mock/BadStorableMock.php +++ b/packages/core/tests/Charcoal/Mock/BadStorableMock.php @@ -9,48 +9,19 @@ /** * */ -class BadStorableMock extends StorableMock +class BadStorableMock extends GenericModel { - const FAIL_AFTER = false; - const FAIL_BEFORE = true; + private bool $failAfter = false; + private bool $failBefore = false; - /** - * Whether to fail before or after an event. - * - * @var boolean - */ - private $fail = self::FAIL_BEFORE; - - /** - * Create new storable mock. - * - * @param boolean $fail TRUE to fail on pre-event, FALSE to fail on post-event. - */ - public function __construct($fail = self::FAIL_BEFORE) + public function failBefore() { - $this->fail = (bool)$fail; - - parent::__construct(); + $this->failBefore = true; } - /** - * Create new storable mock to fail on before events. - * - * @return static - */ - public static function createToFailBefore() - { - return new self(self::FAIL_BEFORE); - } - - /** - * Create new storable mock to fail on after events. - * - * @return static - */ - public static function createToFailAfter() + public function failAfter() { - return new self(self::FAIL_AFTER); + $this->failAfter = true; } /** @@ -61,7 +32,7 @@ public static function createToFailAfter() */ protected function preSave() { - return $this->fail; + return $this->failBefore; } /** @@ -72,7 +43,7 @@ protected function preSave() */ protected function postSave() { - return !$this->fail; + return $this->failAfter; } /** @@ -84,7 +55,7 @@ protected function postSave() */ protected function preUpdate(array $keys = null) { - return $this->fail; + return $this->failBefore; } /** @@ -96,7 +67,7 @@ protected function preUpdate(array $keys = null) */ protected function postUpdate(array $keys = null) { - return !$this->fail; + return $this->failAfter; } /** @@ -107,7 +78,7 @@ protected function postUpdate(array $keys = null) */ protected function preDelete() { - return $this->fail; + return $this->failBefore; } /** @@ -118,6 +89,6 @@ protected function preDelete() */ protected function postDelete() { - return !$this->fail; + return $this->failAfter; } } diff --git a/packages/core/tests/Charcoal/Source/StorableTraitTest.php b/packages/core/tests/Charcoal/Source/StorableTraitTest.php index 83ae6750d..998054ee4 100644 --- a/packages/core/tests/Charcoal/Source/StorableTraitTest.php +++ b/packages/core/tests/Charcoal/Source/StorableTraitTest.php @@ -2,6 +2,9 @@ namespace Charcoal\Tests\Source; +use Charcoal\Model\Service\MetadataLoader; +use Charcoal\Model\Service\ModelLoaderBuilder; +use Charcoal\Tests\Mock\GenericModel; use InvalidArgumentException; use RuntimeException; @@ -27,12 +30,13 @@ */ class StorableTraitTest extends AbstractTestCase { + use \Charcoal\Tests\CoreContainerIntegrationTrait; use ReflectionsTrait; /** * The tested class. * - * @var StorableMock + * @var GenericModel */ public $obj; @@ -43,7 +47,17 @@ class StorableTraitTest extends AbstractTestCase */ protected function setUp(): void { - $this->obj = new StorableMock(); + $container = $this->getContainer(); + + $this->factory = $container['model/factory']; + $this->obj = $this->factory->get(GenericModel::class); + + $source = $this->obj->source(); + if (!$source->tableExists()) { + $source->createTable(); + } + + // $this->obj = new StorableMock(); } /** @@ -210,7 +224,8 @@ public function testSourceFactory() public function testMissingSourceFactory() { $this->expectException(RuntimeException::class); - $this->callMethod($this->obj, 'sourceFactory'); + $obj = new StorableMock(); + $this->callMethod($obj, 'sourceFactory'); } /** @@ -233,24 +248,19 @@ public function testSource() { $obj = $this->obj; - /** 1. Default state is NULL */ - $this->assertNull($this->getPropertyValue($obj, 'source')); - - /** 2. Create repository if state is NULL */ + /** 1. Create repository if state is NULL */ $src1 = $obj->source(); $this->assertInstanceOf(SourceInterface::class, $src1); - $this->assertSame($src1, $this->getPropertyValue($obj, 'source')); - /** 3. Mutated state */ + /** 2. Mutated state */ $src2 = $this->createSource(); $that = $obj->setSource($src2); $this->assertSame($src2, $obj->source()); - $this->assertSame($src2, $this->getPropertyValue($obj, 'source')); - /** 4. Storable can create a repository */ + /** 3. Storable can create a repository */ $this->assertInstanceOf(SourceInterface::class, $this->callMethod($obj, 'createSource')); - /** 5. Chainable */ + /** 4. Chainable */ $this->assertSame($that, $obj); } @@ -278,13 +288,13 @@ public function testSave() $this->assertTrue($obj->save()); /** 2. Fail Early */ - $obj = BadStorableMock::createToFailBefore(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->failBefore(); $this->assertFalse($obj->save()); /** 3. Fail Early */ - $obj = BadStorableMock::createToFailAfter(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->failAfter(); $this->assertFalse($obj->save()); } @@ -312,13 +322,13 @@ public function testUpdate() $this->assertTrue($obj->update()); /** 2. Fail Early */ - $obj = BadStorableMock::createToFailBefore(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->failBefore(); $this->assertFalse($obj->update()); /** 3. Fail Early */ - $obj = BadStorableMock::createToFailAfter(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->failAfter(); $this->assertFalse($obj->update()); } @@ -346,13 +356,15 @@ public function testDelete() $this->assertTrue($obj->delete()); /** 2. Fail Early */ - $obj = BadStorableMock::createToFailBefore(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->setId('123'); + $obj->failBefore(); $this->assertFalse($obj->delete()); /** 3. Fail Early */ - $obj = BadStorableMock::createToFailAfter(); - $obj->setSource($src); + $obj = $this->factory->create(BadStorableMock::class); + $obj->setId('123'); + $obj->failAfter(); $this->assertFalse($obj->delete()); } } diff --git a/packages/email/tests/bootstrap.php b/packages/email/tests/bootstrap.php index 5f58b07cf..a3869fca4 100644 --- a/packages/email/tests/bootstrap.php +++ b/packages/email/tests/bootstrap.php @@ -2,6 +2,7 @@ use Charcoal\App\AppConfig; use Charcoal\App\AppContainer; +use Charcoal\App\Facade\Facade; use Charcoal\Config\GenericConfig; if (($_ENV['TEST_MODE'] ?? '') === 'PACKAGE') { @@ -39,3 +40,6 @@ $GLOBALS['container'] = new AppContainer([ 'config' => $config ]); + +Facade::clearResolvedFacadeInstances(); +Facade::setFacadeResolver($GLOBALS['container']); diff --git a/packages/event/src/Charcoal/Event/ServiceProvider/EventServiceProvider.php b/packages/event/src/Charcoal/Event/ServiceProvider/EventServiceProvider.php index 0776917f8..c4b38a699 100644 --- a/packages/event/src/Charcoal/Event/ServiceProvider/EventServiceProvider.php +++ b/packages/event/src/Charcoal/Event/ServiceProvider/EventServiceProvider.php @@ -23,7 +23,7 @@ class EventServiceProvider implements ServiceProviderInterface public function register(Container $container) { /** - * @param Container $container A service container. + * @param Container $container A service container. * @return EventDispatcherBuilder */ $container['event/dispatcher/builder'] = function (Container $container) { @@ -93,6 +93,10 @@ public function register(Container $container) * @return array */ $container['app/event/listeners'] = function (Container $container): array { + if (!$container->offsetExists('admin/config')) { + return []; + } + return ($container['admin/config']->get('events.listeners') ?? []); }; @@ -104,7 +108,11 @@ public function register(Container $container) * @return array */ $container['app/event/subscribers'] = function (Container $container): array { - return ($container['admin/config'] ->get('events.subscribers') ?? []); + if (!$container->offsetExists('admin/config')) { + return []; + } + + return ($container['admin/config']->get('events.subscribers') ?? []); }; /** @@ -116,6 +124,7 @@ public function register(Container $container) $container['app/event/dispatcher'] = function (Container $container): EventDispatcher { /** @var EventDispatcherBuilder $eventDispatcherBuilder */ $eventDispatcherBuilder = $container['event/dispatcher/builder']; + return $eventDispatcherBuilder->build( $container['app/event/listeners'], $container['app/event/subscribers'] diff --git a/packages/event/tests/Charcoal/Event/ServiceProvider/EventServiceProviderTest.php b/packages/event/tests/Charcoal/Event/ServiceProvider/EventServiceProviderTest.php deleted file mode 100644 index 3207eb676..000000000 --- a/packages/event/tests/Charcoal/Event/ServiceProvider/EventServiceProviderTest.php +++ /dev/null @@ -1,12 +0,0 @@ -assertNull($this->obj['createdBy']); $this->assertNull($this->obj['lastModifiedBy']); - - // Revisionable properties - $this->assertTrue($this->obj['revisionEnabled']); } /** diff --git a/packages/object/tests/Charcoal/Object/ObjectRouteTest.php b/packages/object/tests/Charcoal/Object/ObjectRouteTest.php index 9451fe128..d3c168cd6 100644 --- a/packages/object/tests/Charcoal/Object/ObjectRouteTest.php +++ b/packages/object/tests/Charcoal/Object/ObjectRouteTest.php @@ -2,6 +2,8 @@ namespace Charcoal\Tests\Object; +use Charcoal\App\Facade\Facade; +use Charcoal\Event\ServiceProvider\EventServiceProvider; use DateTime; // From Pimple @@ -170,8 +172,11 @@ private function container() $containerProvider->registerBaseServices($container); $containerProvider->registerModelFactory($container); $containerProvider->registerModelCollectionLoader($container); + $container->register(new EventServiceProvider()); $this->container = $container; + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); } return $this->container; diff --git a/packages/property/tests/Charcoal/Property/ContainerIntegrationTrait.php b/packages/property/tests/Charcoal/Property/ContainerIntegrationTrait.php index 980467f17..df3ee878b 100644 --- a/packages/property/tests/Charcoal/Property/ContainerIntegrationTrait.php +++ b/packages/property/tests/Charcoal/Property/ContainerIntegrationTrait.php @@ -3,6 +3,8 @@ namespace Charcoal\Tests\Property; // From Pimple +use Charcoal\App\Facade\Facade; +use Charcoal\Event\ServiceProvider\EventServiceProvider; use Pimple\Container; // From 'charcoal-property/tests' use Charcoal\Tests\Property\ContainerProvider; @@ -64,8 +66,12 @@ private function setupContainer() $provider->registerPropertyFactory($container); $provider->registerModelFactory($container); $provider->registerModelCollectionLoader($container); + $container->register(new EventServiceProvider()); $this->container = $container; $this->containerProvider = $provider; + + Facade::clearResolvedFacadeInstances(); + Facade::setFacadeResolver($container); } }