Skip to content

Commit

Permalink
Replace ad-hoc Settings implementation with league/config
Browse files Browse the repository at this point in the history
  • Loading branch information
flavioheleno committed Sep 11, 2023
1 parent 527f407 commit 8597c09
Show file tree
Hide file tree
Showing 8 changed files with 492 additions and 259 deletions.
49 changes: 27 additions & 22 deletions app/dependencies.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
use Courier\Serializer\IgBinarySerializer;
use Courier\Transport\AmqpTransport;
use DI\ContainerBuilder;
use League\Config\ConfigurationInterface;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Monolog\Processor\UidProcessor;
use Nyholm\Dsn\DsnParser;
use Nyholm\Psr7\Factory\Psr17Factory;
use PackageHealth\PHP\Application\Settings\SettingsInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
Expand All @@ -34,6 +34,7 @@
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\NullAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;

use function DI\autowire;
Expand All @@ -48,22 +49,28 @@
);
},
Bus::class => function (ContainerInterface $container): Bus {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

$amqp = AmqpTransport::fromDsn($settings->getString('queue.dsn'));
$amqp->setPrefetchCount($settings->getInt('queue.prefetch', 25));
$amqp = AmqpTransport::fromDsn($config->get('queue.dsn'));
$amqp->setPrefetchCount((int)$config->get('queue.prefetch'));

return new Bus(
new SimpleRouter(),
$amqp
);
},
CacheItemPoolInterface::class => function (ContainerInterface $container): CacheItemPoolInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

// disables cache by using a black hole driver
if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
return new ArrayAdapter(
// disables cache by using a null adapter
if ((bool)$config->get('cache.enabled') === false) {
return new NullAdapter();
}

$adapters = [
new ArrayAdapter(
// the default lifetime (in seconds) for cache items that do not define their
// own lifetime, with a value 0 causing items to be stored indefinitely (i.e.
// until the current PHP process finishes)
Expand All @@ -79,20 +86,16 @@
// the maximum number of items that can be stored in the cache. When the limit
// is reached, cache follows the LRU model (least recently used items are deleted)
maxItems: 0
);
}

$adapters = [
new ArrayAdapter()
)
];

if ($settings->has('cache.apcu') && $settings->getBool('cache.apcu.enabled', false)) {
if ((bool)$config->get('cache.apcu.enabled') === true) {
$adapters[] = new ApcuAdapter();
}

if ($settings->has('cache.redis') && $settings->getBool('cache.redis.enabled', false)) {
if ((bool)$config->get('cache.redis.enabled') === true) {
$adapters[] = new RedisAdapter(
RedisAdapter::createConnection($settings->getString('cache.redis.dsn'))
RedisAdapter::createConnection($config->get('cache.redis.dsn'))
);
}

Expand All @@ -112,24 +115,26 @@
return $consumer;
},
LoggerInterface::class => function (ContainerInterface $container): LoggerInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

$logger = new Logger($settings->getString('logger.name'));
$logger = new Logger('app');

$processor = new UidProcessor();
$logger->pushProcessor($processor);

$handler = new StreamHandler(
$settings->getString('logger.path'),
$settings->getString('logger.level')
$config->get('logging.path'),
$config->get('logging.level')
);
$logger->pushHandler($handler);

return $logger;
},
PDO::class => function (ContainerInterface $container): PDO {
$settings = $container->get(SettingsInterface::class);
$dsn = DsnParser::parse($settings->getString('db.dsn'));
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);
$dsn = DsnParser::parse($config->get('db.dsn'));

return new PDO(
sprintf(
Expand Down
27 changes: 16 additions & 11 deletions app/repositories.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
declare(strict_types = 1);

use DI\ContainerBuilder;
use PackageHealth\PHP\Application\Settings\SettingsInterface;
use PackageHealth\PHP\Domain\Dependency\DependencyRepositoryInterface;
use PackageHealth\PHP\Domain\Package\PackageRepositoryInterface;
use PackageHealth\PHP\Domain\Preference\PreferenceRepositoryInterface;
Expand All @@ -18,6 +17,7 @@
use PackageHealth\PHP\Infrastructure\Persistence\Stats\PdoStatsRepository;
use PackageHealth\PHP\Infrastructure\Persistence\Version\CachedVersionRepository;
use PackageHealth\PHP\Infrastructure\Persistence\Version\PdoVersionRepository;
use League\Config\ConfigurationInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Container\ContainerInterface;
use function DI\autowire;
Expand All @@ -28,9 +28,10 @@
// Dependency
PdoDependencyRepository::class => autowire(PdoDependencyRepository::class),
DependencyRepositoryInterface::class => static function (ContainerInterface $container): DependencyRepositoryInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
if ((bool)$config->get('cache.enabled') === false) {
return $container->get(PdoDependencyRepository::class);
}

Expand All @@ -42,9 +43,10 @@
// Package
PdoPackageRepository::class => autowire(PdoPackageRepository::class),
PackageRepositoryInterface::class => static function (ContainerInterface $container): PackageRepositoryInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
if ((bool)$config->get('cache.enabled') === false) {
return $container->get(PdoPackageRepository::class);
}

Expand All @@ -56,9 +58,10 @@
// Preference
PdoPreferenceRepository::class => autowire(PdoPreferenceRepository::class),
PreferenceRepositoryInterface::class => static function (ContainerInterface $container): PreferenceRepositoryInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
if ((bool)$config->get('cache.enabled') === false) {
return $container->get(PdoPreferenceRepository::class);
}

Expand All @@ -70,9 +73,10 @@
// Stats
PdoStatsRepository::class => autowire(PdoStatsRepository::class),
StatsRepositoryInterface::class => static function (ContainerInterface $container): StatsRepositoryInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
if ((bool)$config->get('cache.enabled') === false) {
return $container->get(PdoStatsRepository::class);
}

Expand All @@ -84,9 +88,10 @@
// Version
PdoVersionRepository::class => autowire(PdoVersionRepository::class),
VersionRepositoryInterface::class => static function (ContainerInterface $container): VersionRepositoryInterface {
$settings = $container->get(SettingsInterface::class);
/** @var \League\Config\ConfigurationInterface */
$config = $container->get(ConfigurationInterface::class);

if ($settings->has('cache') === false || $settings->getBool('cache.enabled', false) === false) {
if ((bool)$config->get('cache.enabled') === false) {
return $container->get(PdoVersionRepository::class);
}

Expand Down
93 changes: 82 additions & 11 deletions app/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,81 @@
declare(strict_types = 1);

use DI\ContainerBuilder;
use PackageHealth\PHP\Application\Settings\Settings;
use PackageHealth\PHP\Application\Settings\SettingsInterface;
use League\Config\Configuration;
use League\Config\ConfigurationInterface;
use Nette\Schema\Expect;
use Psr\Log\LogLevel;

return static function (ContainerBuilder $containerBuilder): void {
// Global Settings Object
$containerBuilder->addDefinitions(
[
SettingsInterface::class => static function (): SettingsInterface {
return new Settings(
ConfigurationInterface::class => static function (): ConfigurationInterface {
// config schema
$config = new Configuration(
[
'cache' => Expect::structure(
[
'enabled' => Expect::bool(false),
'apcu' => Expect::structure(
[
'enabled' => Expect::bool(false)
]
),
'redis' => Expect::structure(
[
'enabled' => Expect::bool(false),
'dsn' => Expect::string('redis://localhost:6379')
]
)
]
),
'db' => Expect::structure(
[
'dsn' => Expect::string('pgsql://postgres@localhost:5432/postgres')
]
),
'logging' => Expect::structure(
[
'enabled' => Expect::bool(false),
'level' => Expect::string(LogLevel::INFO),
'path' => Expect::string()->assert(
static function (string $file): bool {
return $file === 'php://stdout' || is_writeable(dirname($file));
}
)
]
),
'queue' => Expect::structure(
[
'dsn' => Expect::string('amqp://guest:guest@localhost:5672/'),
'prefetch' => Expect::int(100)
]
),
'slim' => Expect::structure(
[
// Returns a detailed HTML page with error details and
// a stack trace. Should be disabled in production.
'displayErrorDetails' => Expect::bool(false),
// Whether to display errors on the internal PHP log or not.
'logErrors' => Expect::bool(true),
// If true, display full errors with message and stack trace on the PHP log.
// If false, display only "Slim Application Error" on the PHP log.
// Doesn't do anything when "logErrors" is false.
'logErrorDetails' => Expect::bool(true)
]
)
]
);

// actual values
$config->merge(
[
'cache' => [
'enabled' => PHP_SAPI !== 'cli',
'apcu' => [
'enabled' => extension_loaded('apcu') === true && apcu_enabled() && PHP_SAPI === 'fpm-fcgi'
],
'redis' => [
'enabled' => extension_loaded('redis') === true,
'dsn' => sprintf(
Expand Down Expand Up @@ -46,16 +108,25 @@
),
'prefetch' => 100
],
'displayErrorDetails' => (isset($_ENV['PHP_ENV']) === false || $_ENV['PHP_ENV'] === 'dev'),
'logError' => true,
'logErrorDetails' => true,
'logger' => [
'name' => 'slim-app',
'path' => isset($_ENV['DOCKER']) ? 'php://stdout' : __DIR__ . '/../logs/app.log',
'level' => isset($_ENV['PHP_ENV']) === false || $_ENV['PHP_ENV'] === 'dev' ? LogLevel::DEBUG : LogLevel::INFO
'logging' => [
'path' => (
isset($_ENV['DOCKER']) === true
? 'php://stdout'
: dirname(__DIR__) . '/application.log'
),
'level' => (
$_ENV['PHP_ENV'] === 'prod'
? LogLevel::INFO
: LogLevel::DEBUG
)
],
'slim' => [
'displayErrorDetails' => (isset($_ENV['PHP_ENV']) === false || $_ENV['PHP_ENV'] === 'dev')
]
]
);

return $config->reader();
}
]
);
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"courier/transport-amqp": "dev-legacy",
"flavioheleno/kolekto": "dev-main",
"kriswallsmith/buzz": "^1.2",
"league/config": "^1.2",
"middlewares/minifier": "^2.0",
"middlewares/trailing-slash": "^2.0",
"monolog/monolog": "^3.2",
Expand Down
Loading

0 comments on commit 8597c09

Please sign in to comment.