Refactor facades namespace and update references to use Services\Facades

This commit is contained in:
2025-09-27 09:08:31 -04:00
parent b15827b7b1
commit 44ae5e1392
21 changed files with 332 additions and 28 deletions

View File

@@ -7,7 +7,7 @@ namespace Siteworxpro\App\Controllers;
use League\Route\Http\Exception\NotFoundException;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Facades\Logger;
use Siteworxpro\App\Services\Facades\Logger;
use Siteworxpro\App\Traefik\ProtocolEnum;
abstract class Controller implements ControllerInterface

View File

@@ -7,8 +7,8 @@ namespace Siteworxpro\App\Controllers;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Facades\RedisClient;
class MiddlewaresController extends Controller
{

View File

@@ -7,8 +7,8 @@ namespace Siteworxpro\App\Controllers;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Facades\RedisClient;
class RoutesController extends Controller
{

View File

@@ -7,8 +7,8 @@ namespace Siteworxpro\App\Controllers;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Facades\RedisClient;
class ServicesController extends Controller
{

View File

@@ -9,7 +9,7 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Siteworxpro\App\Facades\Config;
use Siteworxpro\App\Services\Facades\Config;
/**
* Class CorsMiddleware

View File

@@ -6,7 +6,6 @@ namespace Siteworxpro\App;
use Illuminate\Container\Container;
use Illuminate\Database\Capsule\Manager;
use Illuminate\Support\Facades\Facade;
use League\Route\Http\Exception\MethodNotAllowedException;
use League\Route\Http\Exception\NotFoundException;
use League\Route\RouteGroup;
@@ -16,10 +15,11 @@ use Nyholm\Psr7\Factory\Psr17Factory;
use Siteworxpro\App\Controllers\MiddlewaresController;
use Siteworxpro\App\Controllers\RoutesController;
use Siteworxpro\App\Controllers\ServicesController;
use Siteworxpro\App\Facades\Config;
use Siteworxpro\App\Facades\Logger;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Http\Middleware\CorsMiddleware;
use Siteworxpro\App\Services\Facade;
use Siteworxpro\App\Services\Facades\Config;
use Siteworxpro\App\Services\Facades\Logger;
use Spiral\RoadRunner\Http\PSR7Worker;
use Spiral\RoadRunner\Worker;
@@ -67,7 +67,7 @@ class Server
private function boot(): void
{
$container = new Container();
Facade::setFacadeApplication($container);
Facade::setFacadeContainer($container);
$this->worker = new PSR7Worker(
Worker::create(),

308
src/Services/Facade.php Normal file
View File

@@ -0,0 +1,308 @@
<?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);
}
}

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Siteworxpro\App\Facades;
namespace Siteworxpro\App\Services\Facades;
use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\Facades\Facade;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Siteworxpro\App\Facades;
namespace Siteworxpro\App\Services\Facades;
use Illuminate\Support\Facades\Facade;
use RoadRunner\Logger\Logger as RRLogger;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Siteworxpro\App\Facades;
namespace Siteworxpro\App\Services\Facades;
use Illuminate\Support\Facades\Facade;
use Predis\Client;

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
namespace Siteworxpro\App\Facades;
namespace Siteworxpro\App\Services\Facades;
use Illuminate\Support\Facades\Facade;
use Siteworxpro\App\Traefik\EntityEnum;

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\App\Traefik;
use Illuminate\Support\Collection;
use Predis\Collection\Iterator\Keyspace;
use Siteworxpro\App\Facades\Redis;
use Siteworxpro\App\Services\Facades\Redis;
/**
* Class RedisClient

View File

@@ -6,11 +6,7 @@ namespace Siteworxpro\Tests\Controllers;
use League\Route\Http\Exception\NotFoundException;
use Nyholm\Psr7\ServerRequest;
use PHPUnit\Framework\MockObject\Exception;
use Psr\Log\LoggerInterface;
use Siteworxpro\App\Controllers\Controller;
use Siteworxpro\App\Facades\Logger;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;
class ControllerTest extends Unit

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\MiddlewaresController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\RoutesController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\ServicesController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;

View File

@@ -7,8 +7,8 @@ namespace Siteworxpro\Tests\Http\Middleware;
use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Server\RequestHandlerInterface;
use Siteworxpro\App\Facades\Config;
use Siteworxpro\App\Http\Middleware\CorsMiddleware;
use Siteworxpro\App\Services\Facades\Config;
use Siteworxpro\Tests\Unit;
class CorsMiddlewareTest extends Unit

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\Tests\Traefik;
use Mockery;
use Predis\Command\FactoryInterface;
use Siteworxpro\App\Facades\Redis;
use Siteworxpro\App\Services\Facades\Redis;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\App\Traefik\RedisClient;
use Siteworxpro\Tests\Unit;

View File

@@ -6,8 +6,8 @@ namespace Siteworxpro\Tests\Traefik;
use Mockery;
use Predis\Command\FactoryInterface;
use Siteworxpro\App\Facades\Redis;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Services\Facades\Redis;
use Siteworxpro\App\Services\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;

View File

@@ -6,7 +6,7 @@ namespace Siteworxpro\Tests\Traefik;
use Mockery;
use Predis\Command\FactoryInterface;
use Siteworxpro\App\Facades\Redis;
use Siteworxpro\App\Services\Facades\Redis;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\App\Traefik\RedisClient;

View File

@@ -8,8 +8,8 @@ use Illuminate\Container\Container;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Facades\Redis;
use PHPUnit\Framework\TestCase;
use Siteworxpro\App\Facades\Config;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Services\Facades\Config;
use Siteworxpro\App\Services\Facades\RedisClient;
abstract class Unit extends TestCase
{