Skip to content

Commit 16f1a28

Browse files
Introduce Symfony route attributes
1 parent b635a71 commit 16f1a28

File tree

8 files changed

+277
-24
lines changed

8 files changed

+277
-24
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
vendor
22
logs/*
33
data/attachments/*
4+
data/cache/*
45
data-redis
56
data-mysql
67
config.json

composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
"symfony/mailer": "^7",
4040
"symfony/psr-http-message-bridge": "^7.1",
4141
"twig/twig": "^3.0",
42-
"zircote/swagger-php": "^4.7"
42+
"zircote/swagger-php": "^4.7",
43+
"symfony/routing": "^7.1",
44+
"doctrine/annotations": "^2.0"
4345
},
4446
"autoload": {
4547
"psr-4": {

composer.lock

+208-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

data/cache/.gitkeep

Whitespace-only changes.

docker/api/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ COPY docker/api/nginx/sites-enabled/* /etc/nginx/sites-enabled/
3535
RUN sed -i 's/upload_max_filesize = [[:digit:]]\+M/upload_max_filesize = 20M/' /etc/php/${PHP_VERSION}/fpm/php.ini
3636
RUN sed -i 's/post_max_size = [[:digit:]]\+M/post_max_size = 28M/' /etc/php/${PHP_VERSION}/fpm/php.ini
3737

38-
RUN mkdir -p /var/www/webapp /var/www/webapp/data/vendor /var/www/webapp/data/attachments /var/www/webapp/logs && \
38+
RUN mkdir -p /var/www/webapp /var/www/webapp/data/vendor /var/www/webapp/data/attachments /var/www/webapp/data/cache /var/www/webapp/logs && \
3939
chown -R reconmapper:reconmappers /var/www/webapp
4040

4141
RUN chmod -R a+w /var/www/webapp/logs

public/index.php

+59-14
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@
1212
use Reconmap\Services\Logging\LoggingConfigurator;
1313
use Reconmap\Services\SearchListener;
1414
use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;
15+
use Symfony\Component\Config\FileLocator;
1516
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1617
use Symfony\Component\EventDispatcher\EventDispatcher;
18+
use Symfony\Component\HttpFoundation\Request;
1719
use Symfony\Component\HttpFoundation\Response;
20+
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
21+
use Symfony\Component\Routing\Loader\AttributeClassLoader;
22+
use Symfony\Component\Routing\Loader\AttributeDirectoryLoader;
23+
use Symfony\Component\Routing\RequestContext;
24+
use Symfony\Component\Routing\Route;
25+
use Symfony\Component\Routing\Router;
1826

27+
// Load the configuration
1928
$configFilePath = $applicationDir . '/config.json';
2029
if (!file_exists($configFilePath) || !is_readable($configFilePath)) {
2130
$errorMessage = 'Missing or unreadable API configuration file (config.json)';
@@ -31,7 +40,7 @@
3140
$loggingConfigurator = new LoggingConfigurator($logger, $config);
3241
$loggingConfigurator->configure();
3342

34-
$file = $config->getAppDir() . '/data/attachments/container.php';
43+
$file = $config->getAppDir() . '/data/cache/container.php';
3544
if (file_exists($file)) {
3645
require $file;
3746
$container = new CachedApplicationContainer();
@@ -44,22 +53,58 @@
4453
}
4554
ApplicationContainer::initialise($container, $config, $logger);
4655

47-
$request = GuzzleHttp\Psr7\ServerRequest::fromGlobals();
48-
$container->set(Psr\Http\Message\ServerRequestInterface::class, $request);
56+
$request = Request::createFromGlobals();
57+
$requestContext = new RequestContext();
58+
$requestContext->fromRequest($request);
4959

50-
$router = new ApiRouter();
51-
$router->mapRoutes($container, $config);
60+
$controllersDir = $applicationDir . '/src/Controllers';
5261

53-
/**
54-
* @var EventDispatcher $eventDispatcher
55-
*/
56-
$eventDispatcher = $container->get(EventDispatcher::class);
57-
$eventDispatcher->addListener(SearchEvent::class, $container->get(SearchListener::class));
62+
$loader = new AttributeDirectoryLoader(
63+
new FileLocator([$controllersDir]),
64+
new class extends AttributeClassLoader {
65+
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot): void
66+
{
67+
$route->setDefault('_controller', $class->name . '::' . $method->name);
68+
}
69+
}
70+
);
5871

59-
$response = $router->dispatch($request);
72+
$routes = $loader->load($controllersDir);
73+
$router = new Router(
74+
$loader,
75+
$controllersDir,
76+
['cache_dir' => $applicationDir . '/data/cache', 'debug' => false],
77+
$requestContext
78+
);
6079

61-
$httpFoundationFactory = new HttpFoundationFactory();
62-
$symfonyResponse = $httpFoundationFactory->createResponse($response);
80+
try {
81+
// Try routing the request with Symfony's Router
82+
$parameters = $router->match($request->getPathInfo());
83+
$controller = $parameters['_controller'];
84+
unset($parameters['_controller'], $parameters['_route']);
6385

64-
$symfonyResponse->send();
86+
// Call the matched controller
87+
[$class, $method] = explode('::', $controller, 2);
88+
$ooo = $container->get($class);
89+
$response = call_user_func_array([$ooo, $method], $parameters);
90+
} catch (ResourceNotFoundException $e) {
91+
// Fall back to the custom API router
92+
$guzzleRequest = GuzzleHttp\Psr7\ServerRequest::fromGlobals();
93+
$container->set(Psr\Http\Message\ServerRequestInterface::class, $guzzleRequest);
6594

95+
$apiRouter = new ApiRouter();
96+
$apiRouter->mapRoutes($container, $config);
97+
98+
/**
99+
* @var EventDispatcher $eventDispatcher
100+
*/
101+
$eventDispatcher = $container->get(EventDispatcher::class);
102+
$eventDispatcher->addListener(SearchEvent::class, $container->get(SearchListener::class));
103+
104+
$apiResponse = $apiRouter->dispatch($guzzleRequest);
105+
106+
$httpFoundationFactory = new HttpFoundationFactory();
107+
$response = $httpFoundationFactory->createResponse($apiResponse);
108+
}
109+
110+
$response->send();

src/ApiRouter.php

-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ public function mapRoutes(ContainerInterface $container, ApplicationConfig $appl
8484
$securityMiddleware = $container->get(SecurityMiddleware::class);
8585
$cookieMiddleware = $container->get(StaticMiddleware::class);
8686

87-
$this->map('GET', '/openapi.json', GetOpenApiYamlController::class);
8887
$this->map('GET', '/image/{attachmentId:number}', ServeAttachmentController::class)->middlewares([$cookieMiddleware]);
8988

9089
$this->group('', function (RouteGroup $router): void {

0 commit comments

Comments
 (0)