199 lines
8.0 KiB
PHP
199 lines
8.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Définitions PHP-DI.
|
|
*
|
|
* Ce fichier déclare uniquement ce que l'autowiring ne peut pas résoudre seul :
|
|
* - Bindings interface → classe concrète
|
|
* - Classes nécessitant des paramètres scalaires issus de .env ou de chemins filesystem
|
|
*
|
|
* Tout le reste (services, repositories, contrôleurs dont toutes les dépendances
|
|
* sont typées sur des interfaces) est résolu automatiquement par l'autowiring.
|
|
*/
|
|
|
|
use App\Auth\AuthService;
|
|
use App\Auth\AuthServiceInterface;
|
|
use App\Auth\LoginAttemptRepository;
|
|
use App\Auth\LoginAttemptRepositoryInterface;
|
|
use App\Auth\PasswordResetController;
|
|
use App\Auth\PasswordResetRepository;
|
|
use App\Auth\PasswordResetRepositoryInterface;
|
|
use App\Auth\PasswordResetService;
|
|
use App\Auth\PasswordResetServiceInterface;
|
|
use App\Category\CategoryRepository;
|
|
use App\Category\CategoryRepositoryInterface;
|
|
use App\Category\CategoryService;
|
|
use App\Category\CategoryServiceInterface;
|
|
use App\Media\MediaRepository;
|
|
use App\Media\MediaRepositoryInterface;
|
|
use App\Media\MediaService;
|
|
use App\Media\MediaServiceInterface;
|
|
use App\Post\PostRepository;
|
|
use App\Post\PostRepositoryInterface;
|
|
use App\Post\PostService;
|
|
use App\Post\PostServiceInterface;
|
|
use App\Post\RssController;
|
|
use App\Shared\Config;
|
|
use App\Shared\Extension\AppExtension;
|
|
use App\Shared\Html\HtmlPurifierFactory;
|
|
use App\Shared\Html\HtmlSanitizer;
|
|
use App\Shared\Html\HtmlSanitizerInterface;
|
|
use App\Shared\Http\ClientIpResolver;
|
|
use App\Shared\Http\FlashService;
|
|
use App\Shared\Http\FlashServiceInterface;
|
|
use App\Shared\Http\SessionManager;
|
|
use App\Shared\Http\SessionManagerInterface;
|
|
use App\Shared\Mail\MailService;
|
|
use App\Shared\Mail\MailServiceInterface;
|
|
use App\User\UserRepository;
|
|
use App\User\UserRepositoryInterface;
|
|
use App\User\UserService;
|
|
use App\User\UserServiceInterface;
|
|
|
|
use Monolog\Handler\StreamHandler;
|
|
use Monolog\Level;
|
|
use Monolog\Logger;
|
|
use Psr\Log\LoggerInterface;
|
|
use Slim\Views\Twig;
|
|
|
|
use function DI\autowire;
|
|
use function DI\factory;
|
|
|
|
return [
|
|
|
|
// ── Bindings interface → implémentation ──────────────────────────────────
|
|
|
|
AuthServiceInterface::class => autowire(AuthService::class),
|
|
PostServiceInterface::class => autowire(PostService::class),
|
|
UserServiceInterface::class => autowire(UserService::class),
|
|
CategoryServiceInterface::class => autowire(CategoryService::class),
|
|
CategoryRepositoryInterface::class => autowire(CategoryRepository::class),
|
|
MediaRepositoryInterface::class => autowire(MediaRepository::class),
|
|
PostRepositoryInterface::class => autowire(PostRepository::class),
|
|
UserRepositoryInterface::class => autowire(UserRepository::class),
|
|
LoginAttemptRepositoryInterface::class => autowire(LoginAttemptRepository::class),
|
|
PasswordResetRepositoryInterface::class => autowire(PasswordResetRepository::class),
|
|
PasswordResetServiceInterface::class => autowire(PasswordResetService::class),
|
|
FlashServiceInterface::class => autowire(FlashService::class),
|
|
SessionManagerInterface::class => autowire(SessionManager::class),
|
|
HtmlSanitizerInterface::class => autowire(HtmlSanitizer::class),
|
|
|
|
// ── Infrastructure ────────────────────────────────────────────────────────
|
|
|
|
LoggerInterface::class => factory(function (): LoggerInterface {
|
|
$isDev = strtolower($_ENV['APP_ENV'] ?? 'production') === 'development';
|
|
$logger = new Logger('slim-blog');
|
|
$level = $isDev ? Level::Debug : Level::Warning;
|
|
|
|
$logger->pushHandler(
|
|
new StreamHandler(dirname(__DIR__) . '/var/logs/app.log', $level)
|
|
);
|
|
|
|
return $logger;
|
|
}),
|
|
|
|
PDO::class => factory(function (): PDO {
|
|
$pdo = new PDO('sqlite:' . Config::getDatabasePath(), options: [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
]);
|
|
|
|
// strip_tags() PHP exposée comme fonction SQLite pour les triggers FTS5
|
|
$pdo->sqliteCreateFunction('strip_tags', 'strip_tags', 1);
|
|
$pdo->exec('PRAGMA journal_mode=WAL');
|
|
// Attend jusqu'à 3s avant d'échouer sur une contention en écriture
|
|
$pdo->exec('PRAGMA busy_timeout=3000');
|
|
// Réduit les fsync sans sacrifier la cohérence en WAL mode
|
|
$pdo->exec('PRAGMA synchronous=NORMAL');
|
|
// Active l'application réelle des contraintes de clé étrangère.
|
|
// Sans ce pragma, les ON DELETE SET NULL / CASCADE déclarés dans les
|
|
// migrations sont enregistrés dans le schéma mais silencieusement ignorés
|
|
// à l'exécution — SQLite désactive les FK par défaut pour la compatibilité.
|
|
$pdo->exec('PRAGMA foreign_keys=ON');
|
|
|
|
return $pdo;
|
|
}),
|
|
|
|
Twig::class => factory(function (): Twig {
|
|
$isDev = strtolower($_ENV['APP_ENV'] ?? 'production') === 'development';
|
|
|
|
return Twig::create(
|
|
dirname(__DIR__) . '/views',
|
|
['cache' => Config::getTwigCache($isDev)],
|
|
);
|
|
}),
|
|
|
|
\HTMLPurifier::class => factory(function (): \HTMLPurifier {
|
|
return HtmlPurifierFactory::create(dirname(__DIR__) . '/var/cache/htmlpurifier');
|
|
}),
|
|
|
|
// ── Services nécessitant une configuration .env ───────────────────────────
|
|
|
|
MailServiceInterface::class => factory(function (Twig $twig): MailServiceInterface {
|
|
return new MailService(
|
|
twig: $twig,
|
|
host: $_ENV['MAIL_HOST'] ?? '',
|
|
port: (int) ($_ENV['MAIL_PORT'] ?? 587),
|
|
username: $_ENV['MAIL_USERNAME'] ?? '',
|
|
password: $_ENV['MAIL_PASSWORD'] ?? '',
|
|
encryption: strtolower($_ENV['MAIL_ENCRYPTION'] ?? 'tls'),
|
|
from: $_ENV['MAIL_FROM'] ?? '',
|
|
fromName: $_ENV['MAIL_FROM_NAME'] ?? 'Slim Blog',
|
|
);
|
|
}),
|
|
|
|
MediaServiceInterface::class => factory(
|
|
function (MediaRepositoryInterface $mediaRepository, PostRepositoryInterface $postRepository): MediaServiceInterface {
|
|
return new MediaService(
|
|
mediaRepository: $mediaRepository,
|
|
postRepository: $postRepository,
|
|
uploadDir: dirname(__DIR__) . '/public/media',
|
|
uploadUrl: '/media',
|
|
maxSize: (int) ($_ENV['UPLOAD_MAX_SIZE'] ?? 5 * 1024 * 1024),
|
|
);
|
|
}
|
|
),
|
|
|
|
// ── Contrôleurs nécessitant des paramètres scalaires ─────────────────────
|
|
|
|
RssController::class => factory(
|
|
function (PostServiceInterface $postService): RssController {
|
|
return new RssController(
|
|
$postService,
|
|
rtrim($_ENV['APP_URL'] ?? 'http://localhost', '/'),
|
|
$_ENV['APP_NAME'] ?? 'Slim Blog',
|
|
);
|
|
}
|
|
),
|
|
|
|
PasswordResetController::class => factory(
|
|
function (
|
|
Twig $twig,
|
|
PasswordResetServiceInterface $passwordResetService,
|
|
AuthServiceInterface $authService,
|
|
FlashServiceInterface $flash,
|
|
ClientIpResolver $clientIpResolver,
|
|
): PasswordResetController {
|
|
return new PasswordResetController(
|
|
$twig,
|
|
$passwordResetService,
|
|
$authService,
|
|
$flash,
|
|
$clientIpResolver,
|
|
rtrim($_ENV['APP_URL'] ?? 'http://localhost', '/'),
|
|
);
|
|
}
|
|
),
|
|
|
|
ClientIpResolver::class => factory(function (): ClientIpResolver {
|
|
$trusted = array_filter(array_map('trim', explode(',', (string) ($_ENV['TRUSTED_PROXIES'] ?? ''))));
|
|
|
|
return new ClientIpResolver($trusted);
|
|
}),
|
|
|
|
AppExtension::class => factory(function (): AppExtension {
|
|
return new AppExtension(rtrim($_ENV['APP_URL'] ?? 'http://localhost', '/'));
|
|
}),
|
|
];
|