resolved($accessor) === true) { $callback(static::getFacadeRoot(), static::$container); } static::$container->afterResolving($accessor, function ($service, $app) use ($callback) { $callback($service, $app); }); } /** * Convert the facade into a Mockery spy. * * @return MockInterface */ public static function spy(): MockInterface { if (! static::isMock()) { $class = static::getMockableClass(); return tap($class ? Mockery::spy($class) : Mockery::spy(), function ($spy) { static::swap($spy); }); } throw new \RuntimeException('Cannot spy on an existing mock instance.'); } /** * Initiate a partial mock on the facade. * * @return MockInterface */ public static function partialMock(): MockInterface { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->makePartial(); } /** * Initiate a mock expectation on the facade. * * @return Expectation|ExpectationInterface */ public static function shouldReceive(): Mockery\Expectation | Mockery\ExpectationInterface { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->shouldReceive(...func_get_args()); } /** * Initiate a mock expectation on the facade. * * @return Expectation|ExpectationInterface */ public static function expects(): Mockery\Expectation | Mockery\ExpectationInterface { $name = static::getFacadeAccessor(); $mock = static::isMock() ? static::$resolvedInstance[$name] : static::createFreshMockInstance(); return $mock->expects(...func_get_args()); } /** * Create a fresh mock instance for the given class. * * @return MockInterface|LegacyMockInterface */ protected static function createFreshMockInstance(): MockInterface | LegacyMockInterface { return tap(static::createMock(), function ($mock) { static::swap($mock); $mock->shouldAllowMockingProtectedMethods(); }); } /** * Create a fresh mock instance for the given class. * * @return MockInterface */ protected static function createMock(): MockInterface { $class = static::getMockableClass(); return $class ? Mockery::mock($class) : Mockery::mock(); } /** * Determines whether a mock is set as the instance of the facade. * * @return bool */ protected static function isMock(): bool { $name = static::getFacadeAccessor(); return isset(static::$resolvedInstance[$name]) && static::$resolvedInstance[$name] instanceof LegacyMockInterface; } /** * Get the mockable class for the bound instance. * * @return string|null */ protected static function getMockableClass(): ?string { if ($root = static::getFacadeRoot()) { return get_class($root); } return null; } /** * Hotswap the underlying instance behind the facade. * * @param mixed $instance * @return void */ public static function swap(mixed $instance): void { static::$resolvedInstance[static::getFacadeAccessor()] = $instance; if (isset(static::$container)) { static::$container->instance(static::getFacadeAccessor(), $instance); } } /** * Determines whether a "fake" has been set as the facade instance. * * @return bool */ public static function isFake(): bool { $name = static::getFacadeAccessor(); return isset(static::$resolvedInstance[$name]) && static::$resolvedInstance[$name] instanceof Fake; } /** * Get the root object behind the facade. * * @return mixed */ public static function getFacadeRoot(): mixed { return static::resolveFacadeInstance(static::getFacadeAccessor()); } /** * Get the registered name of the component. * * @return string * * @throws \RuntimeException */ protected static function getFacadeAccessor(): string { throw new \RuntimeException('Facade does not implement getFacadeAccessor method.'); } /** * Resolve the facade root instance from the container. * * @param string $name * @return mixed */ protected static function resolveFacadeInstance(string $name): mixed { if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } if (static::$container) { if (static::$cached) { return static::$resolvedInstance[$name] = static::$container[$name]; } return static::$container[$name]; } return null; } /** * Clear a resolved facade instance. * * @param string $name * @return void */ public static function clearResolvedInstance(string $name): void { unset(static::$resolvedInstance[$name]); } /** * Clear all of the resolved instances. * * @return void */ public static function clearResolvedInstances(): void { static::$resolvedInstance = []; } /** * Get the application instance behind the facade. */ public static function getFacadeContainer(): ?Container { return static::$container; } /** * Set the application instance. * * @param Container $container * @return void */ public static function setFacadeContainer(Container $container): void { static::$container = $container; } /** * Handle dynamic, static calls to the object. * * @param string $method * @param array $args * @return mixed * * @throws \RuntimeException */ public static function __callStatic(string $method, array $args) { $instance = static::getFacadeRoot(); if (! $instance) { throw new \RuntimeException('A facade root has not been set.'); } return $instance->$method(...$args); } }