Skip to content

Commit

Permalink
Completed the library class documentations.
Browse files Browse the repository at this point in the history
  • Loading branch information
arabcoders committed Dec 14, 2023
1 parent 1298b95 commit 3c1f125
Show file tree
Hide file tree
Showing 4 changed files with 368 additions and 58 deletions.
15 changes: 15 additions & 0 deletions src/Cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,31 @@

class Cli extends Application
{
/**
* Constructs a new instance of the class.
*
* @param PSRContainer $container The dependency injection container.
*/
public function __construct(protected PSRContainer $container)
{
parent::__construct(self::getAppName(), getAppVersion());
}

/**
* Get the name of the application from the configuration.
*
* @return string The name of the application.
*/
public static function getAppName(): string
{
return Config::get('name');
}

/**
* Get the default input definition for the command.
*
* @return InputDefinition The default input definition.
*/
protected function getDefaultInputDefinition(): InputDefinition
{
$definition = parent::getDefaultInputDefinition();
Expand Down
61 changes: 58 additions & 3 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use App\Backends\Common\ClientInterface as iClient;
use App\Libs\Config;
use Closure;
use DirectoryIterator;
use RuntimeException;
use Symfony\Component\Console\Command\Command as BaseCommand;
Expand All @@ -23,12 +24,28 @@ class Command extends BaseCommand
{
use LockableTrait;

/**
* The DISPLAY_OUTPUT constant represents the available output formats for displaying data.
*
* It is an array containing three possible formats: table, json, and yaml.
*
* @var array<string>
*/
public const DISPLAY_OUTPUT = [
'table',
'json',
'yaml',
];

/**
* Execute the command.
*
* @param InputInterface $input The input object.
* @param OutputInterface $output The output object.
*
* @return int The command exit status.
* @throws RuntimeException If the profiler was enabled and the run was unsuccessful.
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->hasOption('context') && true === $input->getOption('context')) {
Expand Down Expand Up @@ -96,7 +113,15 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return $status;
}

protected function single(\Closure $closure, OutputInterface $output): int
/**
* Executes the provided closure in a single instance, ensuring that only one instance of the command is running at a time.
*
* @param Closure $closure The closure to be executed.
* @param OutputInterface $output The OutputInterface instance for writing output messages.
*
* @return int The return value of the closure.
*/
protected function single(Closure $closure, OutputInterface $output): int
{
try {
if (!$this->lock(getAppVersion() . ':' . $this->getName())) {
Expand All @@ -115,17 +140,25 @@ protected function single(\Closure $closure, OutputInterface $output): int
}
}

/**
* Runs the command and returns the return value.
*
* @param InputInterface $input The InputInterface instance for retrieving input data.
* @param OutputInterface $output The OutputInterface instance for writing output messages.
*
* @return int The return value of the command execution.
*/
protected function runCommand(InputInterface $input, OutputInterface $output): int
{
return self::SUCCESS;
}

/**
* Check Given backends file.
* Check given backends file.
*
* @param string $config custom servers.yaml file.
* @return string
*
* @return string the config file path.
* @throws RuntimeException if there is problem with given config.
*/
protected function checkCustomBackendsFile(string $config): string
Expand Down Expand Up @@ -157,6 +190,15 @@ protected function checkCustomBackendsFile(string $config): string
return $config;
}

/**
* Retrieves the backend client for the specified name.
*
* @param string $name The name of the backend.
* @param array $config (Optional) Override the default configuration for the backend.
*
* @return iClient The backend client instance.
* @throws RuntimeException If no backend with the specified name is found.
*/
protected function getBackend(string $name, array $config = []): iClient
{
if (null === Config::get("servers.{$name}.type", null)) {
Expand All @@ -169,6 +211,13 @@ protected function getBackend(string $name, array $config = []): iClient
return makeBackend(array_replace_recursive($default, $config), $name);
}

/**
* Displays the content in the specified mode.
*
* @param array $content The content to display.
* @param OutputInterface $output The OutputInterface instance for writing output messages.
* @param string $mode The display mode. Default is 'json'.
*/
protected function displayContent(array $content, OutputInterface $output, string $mode = 'json'): void
{
switch ($mode) {
Expand Down Expand Up @@ -222,6 +271,12 @@ protected function displayContent(array $content, OutputInterface $output, strin
}
}

/**
* Completes the input by suggesting values for different options and arguments.
*
* @param CompletionInput $input The CompletionInput instance containing the input data.
* @param CompletionSuggestions $suggestions The CompletionSuggestions instance for suggesting values.
*/
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
{
if ($input->mustSuggestOptionValuesFor('config')) {
Expand Down
124 changes: 95 additions & 29 deletions src/Libs/Initializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,27 @@
use Symfony\Component\Yaml\Yaml;
use Throwable;

/**
* Class Initializer
*
* The Initializer class is responsible for bootstrapping the entire application, for both HTTP and CLI context.
*
* @package Your\Namespace
*/
final class Initializer
{
private Cli $cli;
private ConsoleOutput $cliOutput;
private LoggerInterface|null $accessLog = null;

/**
* Initializes the object.
*
* This method is used to load user custom environment variables, initialize the container,
* initialize the configuration, and add services to the container.
*
* @return void
*/
public function __construct()
{
// -- Load user custom environment variables.
Expand Down Expand Up @@ -65,6 +80,15 @@ public function __construct()
$this->cli = new Cli(Container::getContainer());
}

/**
* Bootstrap the application.
*
* This method is used to create directories, load configuration files, set the default timezone,
* setup error and exception handlers, and return the object.
*
* @return self
* @throws ErrorException If an error occurs.
*/
public function boot(): self
{
$this->createDirectories();
Expand Down Expand Up @@ -112,19 +136,23 @@ function ($severity, $message, $file, $line) {

set_exception_handler(function (Throwable $e) {
Container::get(LoggerInterface::class)->error(
r("{class}: {error} ({file}:{line})." . PHP_EOL, [
'class' => get_class($e),
message: "{class}: {error} ({file}:{line})." . PHP_EOL,
context: [
'class' => $e::class,
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
])
]
);
exit(1);
});

return $this;
}

/**
* Run the application in CLI Context.
*/
public function console(): void
{
try {
Expand All @@ -146,11 +174,11 @@ public function console(): void
}

/**
* Handle HTTP Request.
* Run the application in HTTP Context.
*
* @param iRequest|null $request
* @param iEmitter|null $emitter
* @param null|Closure(iRequest): ResponseInterface $fn
* @param iRequest|null $request If null, the request will be created from globals.
* @param iEmitter|null $emitter If null, the emitter will be created from globals.
* @param null|Closure(iRequest): ResponseInterface $fn If null, the default HTTP server will be used.
*/
public function http(iRequest|null $request = null, iEmitter|null $emitter = null, Closure|null $fn = null): void
{
Expand All @@ -168,27 +196,33 @@ public function http(iRequest|null $request = null, iEmitter|null $emitter = nul
$httpException = (true === ($e instanceof HttpException));

if (false === $httpException || $e->getCode() !== 200) {
Container::get(LoggerInterface::class)->error($e->getMessage(), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
'trace' => $e->getTrace(),
]);
Container::get(LoggerInterface::class)->error(
message: $e->getMessage(),
context: [
'kind' => $e::class,
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace(),
]
);
}

$response = new Response(
$httpException && $e->getCode() >= 200 && $e->getCode() <= 499 ? $e->getCode() : 500,
[
'X-Error-Message' => $httpException ? $e->getMessage() : ''
]
);
$statusCode = $httpException && $e->getCode() >= 200 && $e->getCode() <= 499 ? $e->getCode() : 500;
$response = new Response(status: $statusCode, headers: [
'X-Error-Message' => $httpException ? $e->getMessage() : ''
]);
}

$emitter->emit($response);
}

/**
* @throws InvalidArgumentException
* Handle HTTP requests and process webhooks.
*
* @param iRequest $realRequest The incoming HTTP request.
*
* @return ResponseInterface The HTTP response.
* @throws InvalidArgumentException If an error occurs.
*/
private function defaultHttpServer(iRequest $realRequest): ResponseInterface
{
Expand Down Expand Up @@ -229,16 +263,27 @@ private function defaultHttpServer(iRequest $realRequest): ResponseInterface
try {
$class = makeBackend($info, $name);
} catch (RuntimeException $e) {
$this->write($request, Level::Error, 'An exception was thrown in [{backend}] instance creation.', [
'backend' => $name,
'exception' => [
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
'message' => $e->getMessage(),
'trace' => $e->getTrace(),
$this->write(
request: $request,
level: Level::Error,
message: 'Exception [{error.kind}] was thrown unhandled in [{backend}] instance creation. Error [{error.message} @ {error.file}:{error.line}].',
context: [
'backend' => $name,
'error' => [
'kind' => $e::class,
'line' => $e->getLine(),
'message' => $e->getMessage(),
'file' => after($e->getFile(), ROOT_PATH),
],
'exception' => [
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
'message' => $e->getMessage(),
'trace' => $e->getTrace(),
]
]
]);
);
continue;
}

Expand Down Expand Up @@ -405,6 +450,11 @@ private function defaultHttpServer(iRequest $realRequest): ResponseInterface
return new Response(200);
}

/**
* Create directories based on configuration file.
*
* @throws RuntimeException If the necessary environment variables are not set or if there is an issue creating or accessing directories.
*/
private function createDirectories(): void
{
$dirList = __DIR__ . '/../../config/directories.php';
Expand Down Expand Up @@ -467,6 +517,14 @@ private function createDirectories(): void
}
}

/**
* Set up loggers for the application.
*
* @param Logger $logger The primary application logger.
* @param array $loggers An array of additional loggers and their configurations.
*
* @throws RuntimeException If a logger is missing the 'type' property.
*/
private function setupLoggers(Logger $logger, array $loggers): void
{
$inContainer = inContainer();
Expand Down Expand Up @@ -535,6 +593,14 @@ private function setupLoggers(Logger $logger, array $loggers): void
}
}

/**
* Write a log entry to the access log.
*
* @param iRequest $request The incoming request object.
* @param int|string|Level $level The log level or priority.
* @param string $message The log message.
* @param array $context Additional data/context for the log entry.
*/
private function write(
iRequest $request,
int|string|Level $level,
Expand Down
Loading

0 comments on commit 3c1f125

Please sign in to comment.