Initial commit

This commit is contained in:
2025-12-29 16:27:01 +00:00
committed by Siteworx Pro Gitea
commit 23f2b6432b
147 changed files with 14731 additions and 0 deletions

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

@@ -0,0 +1,278 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services;
use Illuminate\Contracts\Container\Container;
use Illuminate\Support\HigherOrderTapProxy;
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);
});
}
/**
* 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);
}
}
/**
* 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 | null $container
* @return void
*/
public static function setFacadeContainer(Container | null $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

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Siteworxpro\App\Async\Messages\Message;
use Siteworxpro\App\Async\Queues\Queue;
use Siteworxpro\App\Services\Facade;
/**
* Broker Facade
*
* @method static void publish(Queue $queue, Message $message, int $delay = 0)
* @method static void publishLater(Queue $queue, Message $message, int $delay)
* @method static Message|null consume(Queue $queue)
*/
class Broker extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return \Siteworxpro\App\Async\Brokers\Broker::class;
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Siteworxpro\App\CommandBus\Commands\Command;
use Siteworxpro\App\Services\Facade;
/**
* Broker Facade
*
* @package Siteworxpro\App\Services\Facades
* @method static mixed handle(Command $command)
*/
class CommandBus extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return \League\Tactician\CommandBus::class;
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Siteworx\Config\Config as SwConfig;
use Siteworxpro\App\Services\Facade;
/**
* Class Config
*
* This class serves as a facade for the configuration settings of the application.
* It extends the Facade class from the Illuminate\Support\Facades namespace.
*
* @method static array | bool | string | int | null get(string $key) Retrieve the configuration value for the given key. // @codingStandardsIgnoreStart
* @method static void set(string $key, mixed $value) Set the configuration value for the given key. // @codingStandardsIgnoreEnd
*
* @package Siteworx\App\Facades
*/
class Config extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return SwConfig::class;
}
}

View File

@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Siteworxpro\App\Events\Dispatcher as DispatcherConcrete;
use Siteworxpro\App\Services\Facade;
/**
* Class Dispatcher
*
* A facade for the event dispatcher.
*
* @package Siteworxpro\App\Services\Facades
*
* @method static void listen(string $event, callable|string $listener)
* @method static void dispatch(object|string $event, array $payload = [], bool $halt = false)
* @method static void push(object|string $event, array $payload = [])
* @method static array|null until(object|string $event, array $payload = [])
* @method static bool hasListeners(string $eventName)
* @method static void subscribe(mixed $subscriber)
*/
class Dispatcher extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return DispatcherConcrete::class;
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use GuzzleHttp\Client;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7\Response;
use Siteworxpro\App\Services\Facade;
/**
* @method static Response get(string $uri, array $options = [])
* @method static Response post(string $uri, array $options = [])
* @method static Response put(string $uri, array $options = [])
* @method static Response delete(string $uri, array $options = [])
* @method static Response patch(string $uri, array $options = [])
* @method static Response head(string $uri, array $options = [])
* @method static PromiseInterface sendAsync(\Psr\Http\Message\RequestInterface $request, array $options = [])
* @method static PromiseInterface requestAsync(string $method, string $uri, array $options = [])
*/
class Guzzle extends Facade
{
protected static function getFacadeAccessor(): string
{
return Client::class;
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Siteworxpro\App\Services\Facade;
/**
* Class Logger
*
* This class serves as a facade for the Monolog logger.
* It extends the Facade class from the Illuminate\Support\Facades namespace.
*
* @method static debug(\Stringable|string $message, array $context = []) Log an informational message.
* @method static info(\Stringable|string $message, array $context = []) Log an informational message.
* @method static error(\Stringable|string $message, array $context = []) Log an error message.
* @method static warning(\Stringable|string $message, array $context = []) Log a warning message.
* @method static critical(\Stringable|string $message, array $context = []) Log a critical error message.
* @method static alert(\Stringable|string $message, array $context = []) Log an alert message.
* @method static emergency(\Stringable|string $message, array $context = []) Log an emergency message.
*
* @package Siteworxpro\App\Facades
*/
class Logger extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return \Siteworxpro\App\Log\Logger::class;
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Predis\Client;
use Predis\Response\Status;
use Siteworxpro\App\Services\Facade;
/**
* Facade for the Redis client.
*
* This class provides a static interface to interact with the Redis client.
*
* @method static array scan($cursor, ?array $options = null)
* @method static string|null get(string $key)
* @method static Status|null set(string $key, $value, $expireResolution = null, $expireTTL = null, $flag = null)
* @method static array keys(string $pattern)
* @method static int del(string $key)
* @method static Status ping()
*/
class Redis extends Facade
{
/**
* Get the registered name of the component.
*
* @return string The name of the component.
*/
protected static function getFacadeAccessor(): string
{
return Client::class;
}
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\Facades;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use RoadRunner\Logger\Logger;
use Siteworxpro\App\Services\Facade;
use Spiral\Goridge\RPC\RPC;
class RoadRunnerLogger extends Facade
{
/**
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public static function getFacadeRoot(): mixed
{
$container = static::getFacadeContainer();
if ($container && $container->has(Logger::class) === false) {
$rpc = RPC::create($_SERVER['RR_RPC']);
$logger = new Logger($rpc);
$container->bind(static::getFacadeAccessor(), function () use ($logger) {
return $logger;
});
return $logger;
}
return $container->get(Logger::class);
}
protected static function getFacadeAccessor(): string
{
return Logger::class;
}
}

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider;
use Siteworxpro\App\Async\Brokers\Broker;
use Siteworxpro\App\Async\Brokers\Kafka;
use Siteworxpro\App\Async\Brokers\RabbitMQ;
use Siteworxpro\App\Async\Brokers\Redis;
use Siteworxpro\App\Async\Brokers\Sqs;
use Siteworxpro\App\Services\Facades\Config;
/**
* Class BrokerServiceProvider
*
* This service provider is responsible for binding the Broker implementation
* to the Laravel service container based on configuration settings.
*
* @package Siteworxpro\App\Services\ServiceProviders
*/
class BrokerServiceProvider extends ServiceProvider
{
public function provides(): array
{
return [Kafka::class, RabbitMQ::class, Redis::class, Sqs::class];
}
/**
* Register services.
*
* This method binds the Broker interface to a specific implementation
* based on the configuration defined in 'queue.broker' and 'queue.broker_config'.
*
* @return void
* @throws \RuntimeException if the specified broker class does not exist.
*/
public function register(): void
{
$this->app->singleton(Broker::class, function (): Broker {
$configName = Config::get('queue.broker');
$brokerConfig = Config::get('queue.broker_config.' . $configName) ?? [];
$brokerClass = Broker::BROKER_TYPES[$configName] ?? null;
if ($brokerClass && class_exists($brokerClass)) {
return new $brokerClass($brokerConfig);
}
throw new \RuntimeException("Broker class $brokerClass does not exist.");
});
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider;
use League\Tactician\CommandBus;
use League\Tactician\Handler\CommandHandlerMiddleware;
use League\Tactician\Handler\CommandNameExtractor\ClassNameExtractor;
use League\Tactician\Handler\MethodNameInflector\InvokeInflector;
use Siteworxpro\App\CommandBus\AttributeLocator;
/**
* Class CommandBusProvider
*
* @package Siteworxpro\App\Services\ServiceProviders
*/
class CommandBusProvider extends ServiceProvider
{
public function provides(): array
{
return [CommandBus::class];
}
public function register(): void
{
$this->app->singleton(CommandBus::class, function () {
return new CommandBus([
new CommandHandlerMiddleware(
new ClassNameExtractor(),
new AttributeLocator(),
new InvokeInflector()
),
]);
});
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider;
use Siteworxpro\App\Events\Dispatcher;
/**
* Class DispatcherServiceProvider
*
* @package Siteworxpro\App\Services\ServiceProviders
*/
class DispatcherServiceProvider extends ServiceProvider
{
public function provides(): array
{
return [Dispatcher::class];
}
public function register(): void
{
$this->app->singleton(Dispatcher::class, function () {
return new Dispatcher();
});
}
}

View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider;
use Siteworxpro\App\Log\Logger;
use Siteworxpro\App\Services\Facades\Config;
/**
* Class LoggerServiceProvider
*
* @package Siteworxpro\App\Services\ServiceProviders
*/
class LoggerServiceProvider extends ServiceProvider
{
public function provides(): array
{
return [Logger::class];
}
public function register(): void
{
$this->app->singleton(Logger::class, function () {
return new Logger(Config::get('app.log_level'));
});
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Services\ServiceProviders;
use Illuminate\Support\ServiceProvider;
use Predis\Client;
use Siteworxpro\App\Services\Facades\Config;
/**
* Class RedisServiceProvider
*
* This service provider registers a Redis client as a singleton in the application container.
*
* @package Siteworxpro\App\Services\ServiceProviders
*/
class RedisServiceProvider extends ServiceProvider
{
public function provides(): array
{
return [Client::class];
}
public function register(): void
{
$this->app->singleton(Client::class, function () {
return new Client([
'scheme' => 'tcp',
'host' => Config::get('redis.host'),
'port' => Config::get('redis.port'),
'database' => Config::get('redis.database'),
'password' => Config::get('redis.password'),
]);
});
}
}