503 lines
18 KiB
PHP
503 lines
18 KiB
PHP
<?php
|
|
|
|
/**
|
|
* PHP-DI Services
|
|
*/
|
|
|
|
use App\Environment;
|
|
use App\Event;
|
|
use Psr\Container\ContainerInterface;
|
|
|
|
return [
|
|
|
|
// Slim interface
|
|
Slim\Interfaces\RouteCollectorInterface::class => static fn(Slim\App $app) => $app->getRouteCollector(),
|
|
|
|
Slim\Interfaces\RouteParserInterface::class => static fn(
|
|
Slim\Interfaces\RouteCollectorInterface $routeCollector
|
|
) => $routeCollector->getRouteParser(),
|
|
|
|
// URL Router helper
|
|
App\Http\RouterInterface::class => DI\Get(App\Http\Router::class),
|
|
|
|
// Error handler
|
|
Slim\Interfaces\ErrorHandlerInterface::class => DI\Get(App\Http\ErrorHandler::class),
|
|
|
|
// HTTP client
|
|
App\Service\GuzzleFactory::class => static function (Psr\Log\LoggerInterface $logger) {
|
|
$stack = GuzzleHttp\HandlerStack::create();
|
|
|
|
$stack->unshift(
|
|
function (callable $handler) {
|
|
return static function (Psr\Http\Message\RequestInterface $request, array $options) use ($handler) {
|
|
$options[GuzzleHttp\RequestOptions::VERIFY] = Composer\CaBundle\CaBundle::getSystemCaRootBundlePath(
|
|
);
|
|
return $handler($request, $options);
|
|
};
|
|
},
|
|
'ssl_verify'
|
|
);
|
|
|
|
$stack->push(
|
|
GuzzleHttp\Middleware::log(
|
|
$logger,
|
|
new GuzzleHttp\MessageFormatter('HTTP client {method} call to {uri} produced response {code}'),
|
|
Psr\Log\LogLevel::DEBUG
|
|
)
|
|
);
|
|
|
|
return new App\Service\GuzzleFactory(
|
|
[
|
|
'handler' => $stack,
|
|
GuzzleHttp\RequestOptions::HTTP_ERRORS => false,
|
|
GuzzleHttp\RequestOptions::TIMEOUT => 3.0,
|
|
]
|
|
);
|
|
},
|
|
|
|
GuzzleHttp\Client::class => static fn(App\Service\GuzzleFactory $guzzleFactory) => $guzzleFactory->buildClient(),
|
|
|
|
// DBAL
|
|
Doctrine\DBAL\Connection::class => static fn(Doctrine\ORM\EntityManagerInterface $em) => $em->getConnection(),
|
|
|
|
// Doctrine Entity Manager
|
|
App\Doctrine\DecoratedEntityManager::class => static function (
|
|
Psr\Cache\CacheItemPoolInterface $psr6Cache,
|
|
Environment $environment,
|
|
App\Doctrine\Event\StationRequiresRestart $eventRequiresRestart,
|
|
App\Doctrine\Event\AuditLog $eventAuditLog,
|
|
App\Doctrine\Event\SetExplicitChangeTracking $eventChangeTracking,
|
|
Psr\EventDispatcher\EventDispatcherInterface $dispatcher
|
|
) {
|
|
if ($environment->isCli()) {
|
|
$psr6Cache = new Symfony\Component\Cache\Adapter\ArrayAdapter();
|
|
} else {
|
|
$psr6Cache = new Symfony\Component\Cache\Adapter\ProxyAdapter($psr6Cache, 'doctrine.');
|
|
}
|
|
|
|
$dbSettings = $environment->getDatabaseSettings();
|
|
if (isset($dbSettings['unix_socket'])) {
|
|
unset($dbSettings['host'], $dbSettings['port']);
|
|
}
|
|
|
|
$connectionOptions = array_merge(
|
|
$dbSettings,
|
|
[
|
|
'driver' => 'pdo_mysql',
|
|
'charset' => 'utf8mb4',
|
|
'defaultTableOptions' => [
|
|
'charset' => 'utf8mb4',
|
|
'collate' => 'utf8mb4_general_ci',
|
|
],
|
|
'driverOptions' => [
|
|
// PDO::MYSQL_ATTR_INIT_COMMAND = 1002;
|
|
1002 => 'SET NAMES utf8mb4 COLLATE utf8mb4_general_ci',
|
|
// PDO::MYSQL_ATTR_LOCAL_INFILE = 1001
|
|
1001 => true,
|
|
],
|
|
'platform' => new Doctrine\DBAL\Platforms\MariaDb1027Platform(),
|
|
]
|
|
);
|
|
|
|
$mappingClassesPaths = [$environment->getBaseDirectory() . '/src/Entity'];
|
|
|
|
$buildDoctrineMappingPathsEvent = new Event\BuildDoctrineMappingPaths(
|
|
$mappingClassesPaths,
|
|
$environment->getBaseDirectory()
|
|
);
|
|
$dispatcher->dispatch($buildDoctrineMappingPathsEvent);
|
|
|
|
$mappingClassesPaths = $buildDoctrineMappingPathsEvent->getMappingClassesPaths();
|
|
|
|
// Fetch and store entity manager.
|
|
$config = Doctrine\ORM\ORMSetup::createAttributeMetadataConfiguration(
|
|
$mappingClassesPaths,
|
|
!$environment->isProduction(),
|
|
$environment->getTempDirectory() . '/proxies',
|
|
$psr6Cache
|
|
);
|
|
|
|
$config->setAutoGenerateProxyClasses(
|
|
Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_FILE_NOT_EXISTS_OR_CHANGED
|
|
);
|
|
|
|
// Debug mode:
|
|
// $config->setSQLLogger(new Doctrine\DBAL\Logging\EchoSQLLogger);
|
|
|
|
$config->addCustomNumericFunction('RAND', DoctrineExtensions\Query\Mysql\Rand::class);
|
|
|
|
if (!Doctrine\DBAL\Types\Type::hasType('carbon_immutable')) {
|
|
Doctrine\DBAL\Types\Type::addType('carbon_immutable', Carbon\Doctrine\CarbonImmutableType::class);
|
|
}
|
|
|
|
$eventManager = new Doctrine\Common\EventManager();
|
|
$eventManager->addEventSubscriber($eventRequiresRestart);
|
|
$eventManager->addEventSubscriber($eventAuditLog);
|
|
$eventManager->addEventSubscriber($eventChangeTracking);
|
|
|
|
return new App\Doctrine\DecoratedEntityManager(
|
|
fn() => Doctrine\ORM\EntityManager::create($connectionOptions, $config, $eventManager)
|
|
);
|
|
},
|
|
|
|
App\Doctrine\ReloadableEntityManagerInterface::class => DI\Get(App\Doctrine\DecoratedEntityManager::class),
|
|
Doctrine\ORM\EntityManagerInterface::class => DI\Get(App\Doctrine\DecoratedEntityManager::class),
|
|
|
|
// Redis cache
|
|
Redis::class => static function (Environment $environment) {
|
|
if (!$environment->enableRedis()) {
|
|
throw new App\Exception\BootstrapException('Redis is disabled on this installation.');
|
|
}
|
|
|
|
$settings = $environment->getRedisSettings();
|
|
|
|
$redis = new Redis();
|
|
if (isset($settings['socket'])) {
|
|
$redis->connect($settings['socket']);
|
|
} else {
|
|
$redis->connect($settings['host'], $settings['port'], 15);
|
|
}
|
|
$redis->select($settings['db']);
|
|
|
|
return $redis;
|
|
},
|
|
|
|
Symfony\Contracts\Cache\CacheInterface::class => static function (
|
|
Environment $environment,
|
|
Psr\Log\LoggerInterface $logger,
|
|
ContainerInterface $di
|
|
) {
|
|
if ($environment->isTesting()) {
|
|
$cacheInterface = new Symfony\Component\Cache\Adapter\ArrayAdapter();
|
|
} elseif (!$environment->enableRedis()) {
|
|
$tempDir = $environment->getTempDirectory() . DIRECTORY_SEPARATOR . 'cache';
|
|
$cacheInterface = new Symfony\Component\Cache\Adapter\FilesystemAdapter(
|
|
'',
|
|
0,
|
|
$tempDir
|
|
);
|
|
} else {
|
|
$cacheInterface = new Symfony\Component\Cache\Adapter\RedisAdapter($di->get(Redis::class));
|
|
}
|
|
|
|
$cacheInterface->setLogger($logger);
|
|
return $cacheInterface;
|
|
},
|
|
|
|
Symfony\Component\Cache\Adapter\AdapterInterface::class => DI\get(
|
|
Symfony\Contracts\Cache\CacheInterface::class
|
|
),
|
|
Psr\Cache\CacheItemPoolInterface::class => DI\get(
|
|
Symfony\Contracts\Cache\CacheInterface::class
|
|
),
|
|
Psr\SimpleCache\CacheInterface::class => static function (Psr\Cache\CacheItemPoolInterface $cache) {
|
|
return new Symfony\Component\Cache\Psr16Cache($cache);
|
|
},
|
|
|
|
// Symfony Lock adapter
|
|
Symfony\Component\Lock\PersistingStoreInterface::class => static function (
|
|
ContainerInterface $di,
|
|
Environment $environment
|
|
) {
|
|
if ($environment->enableRedis()) {
|
|
$redis = $di->get(Redis::class);
|
|
$store = new Symfony\Component\Lock\Store\RedisStore($redis);
|
|
} else {
|
|
$store = new Symfony\Component\Lock\Store\FlockStore($environment->getTempDirectory());
|
|
}
|
|
|
|
return $store;
|
|
},
|
|
|
|
// Console
|
|
App\Console\Application::class => static function (
|
|
DI\Container $di,
|
|
App\CallableEventDispatcherInterface $dispatcher,
|
|
App\Version $version,
|
|
Environment $environment
|
|
) {
|
|
$console = new App\Console\Application(
|
|
$environment->getAppName() . ' Command Line Tools ('
|
|
. $environment->getAppEnvironmentEnum()->getName() . ')',
|
|
$version->getVersion()
|
|
);
|
|
$console->setDispatcher($dispatcher);
|
|
|
|
// Trigger an event for the core app and all plugins to build their CLI commands.
|
|
$event = new Event\BuildConsoleCommands($console, $di);
|
|
$dispatcher->dispatch($event);
|
|
|
|
$commandLoader = new Symfony\Component\Console\CommandLoader\ContainerCommandLoader(
|
|
$di,
|
|
$event->getAliases()
|
|
);
|
|
$console->setCommandLoader($commandLoader);
|
|
|
|
return $console;
|
|
},
|
|
|
|
// Event Dispatcher
|
|
App\CallableEventDispatcherInterface::class => static function (
|
|
DI\Container $di,
|
|
App\Plugins $plugins
|
|
) {
|
|
$dispatcher = new App\CallableEventDispatcher($di);
|
|
|
|
// Register application default events.
|
|
if (file_exists(__DIR__ . '/events.php')) {
|
|
call_user_func(include(__DIR__ . '/events.php'), $dispatcher);
|
|
}
|
|
|
|
// Register plugin-provided events.
|
|
$plugins->registerEvents($dispatcher);
|
|
|
|
return $dispatcher;
|
|
},
|
|
Psr\EventDispatcher\EventDispatcherInterface::class => DI\get(
|
|
App\CallableEventDispatcherInterface::class
|
|
),
|
|
|
|
// Monolog Logger
|
|
Monolog\Logger::class => static function (Environment $environment) {
|
|
$logger = new Monolog\Logger($environment->getAppName());
|
|
$loggingLevel = $environment->getLogLevel();
|
|
|
|
if ($environment->isCli() || $environment->isDocker()) {
|
|
$log_stderr = new Monolog\Handler\StreamHandler('php://stderr', $loggingLevel, true);
|
|
$logger->pushHandler($log_stderr);
|
|
}
|
|
|
|
$log_file = new Monolog\Handler\RotatingFileHandler(
|
|
$environment->getTempDirectory() . '/app.log',
|
|
5,
|
|
$loggingLevel,
|
|
true
|
|
);
|
|
$logger->pushHandler($log_file);
|
|
|
|
return $logger;
|
|
},
|
|
Psr\Log\LoggerInterface::class => DI\get(Monolog\Logger::class),
|
|
|
|
// Doctrine annotations reader
|
|
Doctrine\Common\Annotations\Reader::class => static function (
|
|
Psr\Cache\CacheItemPoolInterface $psr6Cache,
|
|
Environment $settings
|
|
) {
|
|
$proxyCache = new Symfony\Component\Cache\Adapter\ProxyAdapter($psr6Cache, 'annotations.');
|
|
|
|
return new Doctrine\Common\Annotations\PsrCachedReader(
|
|
new Doctrine\Common\Annotations\AnnotationReader(),
|
|
$proxyCache,
|
|
!$settings->isProduction()
|
|
);
|
|
},
|
|
|
|
// Symfony Serializer
|
|
Symfony\Component\Serializer\Serializer::class => static function (
|
|
Doctrine\Common\Annotations\Reader $reader,
|
|
Doctrine\ORM\EntityManagerInterface $em
|
|
) {
|
|
$classMetaFactory = new Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory(
|
|
new Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader($reader)
|
|
);
|
|
|
|
$normalizers = [
|
|
new Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer(),
|
|
new App\Normalizer\DoctrineEntityNormalizer($em, $classMetaFactory),
|
|
new Symfony\Component\Serializer\Normalizer\ObjectNormalizer($classMetaFactory),
|
|
];
|
|
$encoders = [
|
|
new Symfony\Component\Serializer\Encoder\JsonEncoder(),
|
|
];
|
|
|
|
return new Symfony\Component\Serializer\Serializer($normalizers, $encoders);
|
|
},
|
|
|
|
// Symfony Validator
|
|
Symfony\Component\Validator\Validator\ValidatorInterface::class => static function (
|
|
Doctrine\Common\Annotations\Reader $reader,
|
|
Symfony\Component\Validator\ContainerConstraintValidatorFactory $constraintValidatorFactory
|
|
) {
|
|
$builder = new Symfony\Component\Validator\ValidatorBuilder();
|
|
$builder->setConstraintValidatorFactory($constraintValidatorFactory);
|
|
$builder->enableAnnotationMapping();
|
|
$builder->setDoctrineAnnotationReader($reader);
|
|
|
|
return $builder->getValidator();
|
|
},
|
|
|
|
Pheanstalk\Pheanstalk::class => static fn() => Pheanstalk\Pheanstalk::create('127.0.0.1', 11300),
|
|
|
|
App\MessageQueue\QueueManagerInterface::class => static function (
|
|
Environment $environment,
|
|
ContainerInterface $di
|
|
) {
|
|
if ($environment->isTesting()) {
|
|
return new App\MessageQueue\TestQueueManager();
|
|
}
|
|
|
|
$pheanstalk = $di->get(Pheanstalk\Pheanstalk::class);
|
|
return new App\MessageQueue\QueueManager($pheanstalk);
|
|
},
|
|
|
|
Symfony\Component\Messenger\MessageBus::class => static function (
|
|
App\MessageQueue\QueueManager $queueManager,
|
|
App\Lock\LockFactory $lockFactory,
|
|
Monolog\Logger $logger,
|
|
ContainerInterface $di,
|
|
App\Plugins $plugins,
|
|
Environment $environment
|
|
) {
|
|
$loggingLevel = $environment->getLogLevel();
|
|
$busLogger = new Psr\Log\NullLogger();
|
|
|
|
// Configure message sending middleware
|
|
$sendMessageMiddleware = new Symfony\Component\Messenger\Middleware\SendMessageMiddleware($queueManager);
|
|
$sendMessageMiddleware->setLogger($busLogger);
|
|
|
|
// Configure message handling middleware
|
|
$handlers = [];
|
|
$receivers = require __DIR__ . '/messagequeue.php';
|
|
|
|
// Register plugin-provided message queue receivers
|
|
$receivers = $plugins->registerMessageQueueReceivers($receivers);
|
|
|
|
foreach ($receivers as $messageClass => $handlerClass) {
|
|
$handlers[$messageClass][] = static function ($message) use ($handlerClass, $di) {
|
|
$obj = $di->get($handlerClass);
|
|
return $obj($message);
|
|
};
|
|
}
|
|
|
|
$handlersLocator = new Symfony\Component\Messenger\Handler\HandlersLocator($handlers);
|
|
|
|
$handleMessageMiddleware = new Symfony\Component\Messenger\Middleware\HandleMessageMiddleware(
|
|
$handlersLocator,
|
|
true
|
|
);
|
|
$handleMessageMiddleware->setLogger($busLogger);
|
|
|
|
// Add unique protection middleware
|
|
$uniqueMiddleware = new App\MessageQueue\HandleUniqueMiddleware($lockFactory);
|
|
|
|
// On testing, messages are handled directly when called
|
|
if ($environment->isTesting()) {
|
|
return new Symfony\Component\Messenger\MessageBus(
|
|
[
|
|
$handleMessageMiddleware,
|
|
]
|
|
);
|
|
}
|
|
|
|
// Compile finished message bus.
|
|
return new Symfony\Component\Messenger\MessageBus(
|
|
[
|
|
$sendMessageMiddleware,
|
|
$uniqueMiddleware,
|
|
$handleMessageMiddleware,
|
|
]
|
|
);
|
|
},
|
|
|
|
Symfony\Component\Messenger\MessageBusInterface::class => DI\get(
|
|
Symfony\Component\Messenger\MessageBus::class
|
|
),
|
|
|
|
// Mail functionality
|
|
Symfony\Component\Mailer\Transport\TransportInterface::class => static function (
|
|
App\Entity\Repository\SettingsRepository $settingsRepo,
|
|
Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher,
|
|
Monolog\Logger $logger
|
|
) {
|
|
$settings = $settingsRepo->readSettings();
|
|
|
|
if ($settings->getMailEnabled()) {
|
|
$requiredSettings = [
|
|
'mailSenderEmail' => $settings->getMailSenderEmail(),
|
|
'mailSmtpHost' => $settings->getMailSmtpHost(),
|
|
'mailSmtpPort' => $settings->getMailSmtpPort(),
|
|
];
|
|
|
|
$hasAllSettings = true;
|
|
foreach ($requiredSettings as $setting) {
|
|
if (empty($setting)) {
|
|
$hasAllSettings = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($hasAllSettings) {
|
|
$transport = new Symfony\Component\Mailer\Transport\Smtp\EsmtpTransport(
|
|
$settings->getMailSmtpHost(),
|
|
$settings->getMailSmtpPort(),
|
|
$settings->getMailSmtpSecure(),
|
|
$eventDispatcher,
|
|
$logger
|
|
);
|
|
|
|
if (!empty($settings->getMailSmtpUsername())) {
|
|
$transport->setUsername($settings->getMailSmtpUsername());
|
|
$transport->setPassword($settings->getMailSmtpPassword());
|
|
}
|
|
|
|
return $transport;
|
|
}
|
|
}
|
|
|
|
return new Symfony\Component\Mailer\Transport\NullTransport(
|
|
$eventDispatcher,
|
|
$logger
|
|
);
|
|
},
|
|
|
|
Symfony\Component\Mailer\Mailer::class => static fn(
|
|
Symfony\Component\Mailer\Transport\TransportInterface $transport,
|
|
Symfony\Component\Messenger\MessageBus $messageBus,
|
|
Psr\EventDispatcher\EventDispatcherInterface $eventDispatcher
|
|
) => new Symfony\Component\Mailer\Mailer($transport, $messageBus, $eventDispatcher),
|
|
|
|
Symfony\Component\Mailer\MailerInterface::class => DI\get(
|
|
Symfony\Component\Mailer\Mailer::class
|
|
),
|
|
|
|
// Supervisor manager
|
|
Supervisor\SupervisorInterface::class => static fn(
|
|
Environment $environment,
|
|
Psr\Log\LoggerInterface $logger
|
|
) => new Supervisor\Supervisor(
|
|
new fXmlRpc\Client(
|
|
'http://localhost/RPC2',
|
|
new fXmlRpc\Transport\PsrTransport(
|
|
new GuzzleHttp\Psr7\HttpFactory(),
|
|
new GuzzleHttp\Client([
|
|
'curl' => [
|
|
\CURLOPT_UNIX_SOCKET_PATH => '/var/run/supervisor.sock',
|
|
],
|
|
])
|
|
)
|
|
),
|
|
$logger
|
|
),
|
|
|
|
// NowPlaying Adapter factory
|
|
NowPlaying\AdapterFactory::class => static function (
|
|
GuzzleHttp\Client $httpClient,
|
|
Psr\Log\LoggerInterface $logger
|
|
) {
|
|
$httpFactory = new GuzzleHttp\Psr7\HttpFactory();
|
|
|
|
return new NowPlaying\AdapterFactory(
|
|
$httpFactory,
|
|
$httpFactory,
|
|
$httpClient,
|
|
$logger
|
|
);
|
|
},
|
|
|
|
App\Webhook\ConnectorLocator::class => static fn(ContainerInterface $di) => new App\Webhook\ConnectorLocator(
|
|
$di,
|
|
require __DIR__ . '/webhooks.php'
|
|
),
|
|
];
|