diff --git a/README.md b/README.md index f69fe2e..497edeb 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,8 @@ composer require codefyphp/codefy ## 📘 Documentation Documentation is still a work in progress. Between the [Qubus Components](https://docs.qubusphp.com/) documentation -and [CodefyPHP's](https://codefyphp.com/documentation/) documentation, that should help you get started. If you have questions or -need help, feel free to ask for help in the [forums](https://codefyphp.com/community/). +and [CodefyPHP's](https://codefyphp.com/docs/) documentation, that should help you get started. If you have questions or +need help, feel free to ask for help in the [forums](https://forum.codefyphp.com/). ## 🙌 Sponsors diff --git a/composer.json b/composer.json index e3b592a..261da9e 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "codefyphp/domain-driven-core": "^3", "composer/class-map-generator": "^1", "dragonmantank/cron-expression": "^3", + "forxer/gravatar": "^5.0", "melbahja/seo": "^2", "middlewares/cache": "^3", "middlewares/minifier": "^2", diff --git a/src/Configuration/Middleware.php b/src/Configuration/Middleware.php new file mode 100644 index 0000000..3c614cc --- /dev/null +++ b/src/Configuration/Middleware.php @@ -0,0 +1,30 @@ +merge(self::$customAliases); + } +} diff --git a/src/Console/Commands/UlidCommand.php b/src/Console/Commands/Domain/UlidCommand.php similarity index 94% rename from src/Console/Commands/UlidCommand.php rename to src/Console/Commands/Domain/UlidCommand.php index 1d69698..da8049d 100644 --- a/src/Console/Commands/UlidCommand.php +++ b/src/Console/Commands/Domain/UlidCommand.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Codefy\Framework\Console\Commands; +namespace Codefy\Framework\Console\Commands\Domain; use Codefy\Framework\Application; use Codefy\Framework\Console\ConsoleCommand; diff --git a/src/Console/Commands/UuidCommand.php b/src/Console/Commands/Domain/UuidCommand.php similarity index 94% rename from src/Console/Commands/UuidCommand.php rename to src/Console/Commands/Domain/UuidCommand.php index ae01ad3..d683964 100644 --- a/src/Console/Commands/UuidCommand.php +++ b/src/Console/Commands/Domain/UuidCommand.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Codefy\Framework\Console\Commands; +namespace Codefy\Framework\Console\Commands\Domain; use Codefy\Framework\Application; use Codefy\Framework\Console\ConsoleCommand; diff --git a/src/Console/ConsoleKernel.php b/src/Console/ConsoleKernel.php index eca4301..3967ba8 100644 --- a/src/Console/ConsoleKernel.php +++ b/src/Console/ConsoleKernel.php @@ -197,6 +197,7 @@ protected function load(array $commands = []): void * * @throws CommandNotFoundException * @throws Exception + * @throws Throwable */ public function call(string $command, array $parameters = [], bool|OutputInterface|null $outputBuffer = null): int { diff --git a/src/Helpers/core.php b/src/Helpers/core.php index 13ddfb8..c11dda3 100644 --- a/src/Helpers/core.php +++ b/src/Helpers/core.php @@ -23,10 +23,16 @@ use Codefy\QueryBus\Query; use Codefy\QueryBus\Resolvers\NativeQueryHandlerResolver; use Codefy\QueryBus\UnresolvableQueryHandlerException; +use Gravatar\Image; +use Gravatar\Profile; +use Psr\Http\Message\ResponseInterface; use Qubus\Exception\Exception; use Qubus\Expressive\Connection; use Qubus\Expressive\QueryBuilder; +use Qubus\Http\Factories\HtmlResponseFactory; +use Qubus\View\Renderer; use ReflectionException; +use RuntimeException; use function dirname; use function error_log; @@ -427,3 +433,60 @@ function queue(ShouldQueue $queue): NodeQueue { return new NodeQueue($queue); } + +/** + * Return a new Gravatar Image instance. + * + * @param string|null $email + * @return Image + */ +function gravatar(?string $email = null): Image +{ + return new Image($email); +} + +/** + * Return a new Gravatar Profile instance. + * + * @param string|null $email + * @return Profile + */ +function gravatar_profile(?string $email = null): Profile +{ + return new Profile($email); +} + +/** + * Throw the given exception if the given condition is true. + * + * @param mixed $condition + * @param string $exception + * @param ...$parameters + * @return mixed + */ +function throw_if(mixed $condition, string $exception = RuntimeException::class, ...$parameters): mixed +{ + if ($condition) { + if (is_string($exception) && class_exists($exception)) { + $exception = new $exception(...$parameters); + } + + throw is_string($exception) ? new RuntimeException($exception) : $exception; + } + + return $condition; +} + +/** + * @param array|string $template + * @param array $data + * @return ResponseInterface + * @throws \Exception + */ +function view(array|string $template, array $data = []): ResponseInterface +{ + /** @var Renderer $template */ + $template = Codefy::$PHP->make(name: Renderer::class); + + return HtmlResponseFactory::create($template->render($template, $data)); +} diff --git a/src/Http/Middleware/ExceptionMiddleware.php b/src/Http/Middleware/ExceptionMiddleware.php new file mode 100644 index 0000000..0431069 --- /dev/null +++ b/src/Http/Middleware/ExceptionMiddleware.php @@ -0,0 +1,65 @@ +handle($request); + } catch (HttpException | Psr7Exception $e) { + $this->app->flash->error($e->getMessage()); + + $this->logException($e); + + return RedirectResponseFactory::create( + uri: $e->getUri() ?? $request->getServerParams()['HTTP_REFERER'] ?? '/', + ); + } catch (Throwable $t) { + $this->app->flash->error('Internal Error'); + + $this->logException($t); + + return RedirectResponseFactory::create( + uri: $request->getServerParams()['HTTP_REFERER'] ?? '/', + ); + } + + return $response; + } + + /** + * @throws ReflectionException + * @throws TypeException + */ + protected function logException(Throwable $t, array $context = []): void + { + $psrLogger = new Psr3ErrorHandler($this->app->getLogger()); + $psrLogger->handle($t, $context); + } +} diff --git a/src/Support/DefaultCommands.php b/src/Support/DefaultCommands.php index fa97703..ed7e3af 100644 --- a/src/Support/DefaultCommands.php +++ b/src/Support/DefaultCommands.php @@ -27,8 +27,8 @@ public function __construct(array $collection = []) \Codefy\Framework\Console\Commands\MigrateRedoCommand::class, \Codefy\Framework\Console\Commands\ScheduleListCommand::class, \Codefy\Framework\Console\Commands\ServeCommand::class, - \Codefy\Framework\Console\Commands\UuidCommand::class, - \Codefy\Framework\Console\Commands\UlidCommand::class, + \Codefy\Framework\Console\Commands\Domain\UuidCommand::class, + \Codefy\Framework\Console\Commands\Domain\UlidCommand::class, \Codefy\Framework\Console\Commands\FlushPipelineCommand::class, \Codefy\Framework\Console\Commands\VendorPublishCommand::class, \Codefy\Framework\Console\Commands\GenerateEncryptionKeyCommand::class, diff --git a/src/Support/DefaultMiddlewares.php b/src/Support/DefaultMiddlewares.php new file mode 100644 index 0000000..8b4391f --- /dev/null +++ b/src/Support/DefaultMiddlewares.php @@ -0,0 +1,40 @@ +collection = $collection ?: [ + 'api' => \Codefy\Framework\Http\Middleware\ApiMiddleware::class, + 'security.headers' => \Codefy\Framework\Http\Middleware\SecureHeaders\ContentSecurityPolicyMiddleware::class, + 'content.cache' => \Codefy\Framework\Http\Middleware\ContentCacheMiddleware::class, + 'cors' => \Codefy\Framework\Http\Middleware\CorsMiddleware::class, + 'csrf.token' => \Codefy\Framework\Http\Middleware\Csrf\CsrfTokenMiddleware::class, + 'csrf.protection' => \Codefy\Framework\Http\Middleware\Csrf\CsrfProtectionMiddleware::class, + 'css.minify' => \Codefy\Framework\Http\Middleware\CssMinifierMiddleware::class, + 'honeypot' => \Codefy\Framework\Http\Middleware\Spam\HoneyPotMiddleware::class, + 'html.minify' => \Codefy\Framework\Http\Middleware\HtmlMinifierMiddleware::class, + 'http.cache' => \Codefy\Framework\Http\Middleware\Cache\CacheMiddleware::class, + 'http.cache.clear.data' => \Codefy\Framework\Http\Middleware\Cache\ClearSiteDataMiddleware::class, + 'http.cache.expires' => \Codefy\Framework\Http\Middleware\Cache\CacheExpiresMiddleware::class, + 'http.cache.prevention' => \Codefy\Framework\Http\Middleware\Cache\CachePreventionMiddleware::class, + 'js.minify' => \Codefy\Framework\Http\Middleware\JsMinifierMiddleware::class, + 'rate.limiter' => \Codefy\Framework\Http\Middleware\ThrottleMiddleware::class, + 'referrer.spam' => \Codefy\Framework\Http\Middleware\Spam\ReferrerSpamMiddleware::class, + 'user.authenticate' => \Codefy\Framework\Http\Middleware\Auth\AuthenticationMiddleware::class, + 'user.session' => \Codefy\Framework\Http\Middleware\Auth\UserSessionMiddleware::class, + 'user.authorization' => \Codefy\Framework\Http\Middleware\Auth\UserAuthorizationMiddleware::class, + 'user.session.expire' => \Codefy\Framework\Http\Middleware\Auth\ExpireUserSessionMiddleware::class, + 'php.debugbar' => \Codefy\Framework\Http\Middleware\DebugBarMiddleware::class, + 'http.exception' => \Codefy\Framework\Http\Middleware\ExceptionMiddleware::class, + ]; + } +}