You've already forked Php-Template
All checks were successful
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 1m53s
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m4s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 2m7s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Successful in 1m57s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 2m44s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Successful in 52s
🏗️✨ Build Workflow / 🖥️ 🔨 Build (push) Successful in 3m13s
Reviewed-on: #4 Co-authored-by: Ron Rise <ron@siteworxpro.com> Co-committed-by: Ron Rise <ron@siteworxpro.com>
309 lines
7.4 KiB
PHP
309 lines
7.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Siteworxpro\App\Services;
|
|
|
|
use Illuminate\Contracts\Container\Container;
|
|
use Illuminate\Support\Testing\Fakes\Fake;
|
|
use Mockery;
|
|
use Mockery\Expectation;
|
|
use Mockery\ExpectationInterface;
|
|
use Mockery\LegacyMockInterface;
|
|
use Mockery\MockInterface;
|
|
|
|
class Facade
|
|
{
|
|
/**
|
|
* The application instance being facaded.
|
|
*
|
|
* @var Container | null
|
|
*/
|
|
protected static ?Container $container = null;
|
|
|
|
/**
|
|
* The resolved object instances.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected static array $resolvedInstance;
|
|
|
|
/**
|
|
* Indicates if the resolved instance should be cached.
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected static bool $cached = true;
|
|
|
|
/**
|
|
* Run a Closure when the facade has been resolved.
|
|
*
|
|
* @param \Closure $callback
|
|
* @return void
|
|
*/
|
|
public static function resolved(\Closure $callback): void
|
|
{
|
|
$accessor = static::getFacadeAccessor();
|
|
|
|
if (static::$container->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);
|
|
}
|
|
}
|