gmarche/src/Framework/App.php

151 lines
3.8 KiB
PHP

<?php
namespace Framework;
use DI\ContainerBuilder;
use Doctrine\Common\Cache\ApcuCache;
use Doctrine\Common\Cache\FilesystemCache;
use Framework\Middleware\CombinedMiddleware;
use Framework\Middleware\RoutePrefixedMiddleware;
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class App implements DelegateInterface
{
/**
* List of modules
* @var array
*/
private $modules = [];
/**
* @var array
*/
private $definitions;
/**
* @var ContainerInterface
*/
private $container;
/**
* @var string[]
*/
private $middlewares = [];
/**
* @var int
*/
private $index = 0;
/**
* App constructor.
* @param null|string|array $definitions
*/
public function __construct($definitions = [])
{
if (is_string($definitions)) {
$definitions = [$definitions];
}
if (!$this->isSequential($definitions)) {
$definitions = [$definitions];
}
$this->definitions = $definitions;
}
/**
* Rajoute un module à l'application
*
* @param string $module
* @return App
*/
public function addModule(string $module): self
{
$this->modules[] = $module;
return $this;
}
/**
* Ajoute un middleware
*
* @param string|callable|MiddlewareInterface $routePrefix
* @param null|string|callable|MiddlewareInterface $middleware
* @return App
*/
public function pipe($routePrefix, $middleware = null): self
{
if ($middleware === null) {
$this->middlewares[] = $routePrefix;
} else {
$this->middlewares[] = new RoutePrefixedMiddleware($this->getContainer(), $routePrefix, $middleware);
}
return $this;
}
public function process(ServerRequestInterface $request): ResponseInterface
{
$this->index++;
if ($this->index > 1) {
throw new \Exception();
}
$middleware = new CombinedMiddleware($this->getContainer(), $this->middlewares);
return $middleware->process($request, $this);
}
public function run(ServerRequestInterface $request): ResponseInterface
{
foreach ($this->modules as $module) {
$this->getContainer()->get($module);
}
return $this->process($request);
}
/**
* @return ContainerInterface
*/
public function getContainer(): ContainerInterface
{
if ($this->container === null) {
$builder = new ContainerBuilder();
$env = getenv('ENV') ?: 'production';
if ($env === 'production') {
//$builder->setDefinitionCache(new FilesystemCache('tmp/di'));
$builder->writeProxiesToFile(true, 'tmp/proxies');
}
foreach ($this->definitions as $definition) {
$builder->addDefinitions($definition);
}
foreach ($this->modules as $module) {
if ($module::DEFINITIONS) {
$builder->addDefinitions($module::DEFINITIONS);
}
}
$builder->addDefinitions([
App::class => $this
]);
$this->container = $builder->build();
}
return $this->container;
}
/**
* @return array
*/
public function getModules(): array
{
return $this->modules;
}
private function isSequential(array $array): bool
{
if (empty($array)) {
return true;
}
return array_keys($array) === range(0, count($array) - 1);
}
}