Use container for dependencies

This looks more complicated but removes a lot of hard coded class connections
and will make injecting config easier.
This commit is contained in:
James Gilliland 2022-03-05 13:57:22 -06:00
parent e8724f4513
commit 12211289bf
11 changed files with 156 additions and 37 deletions

View file

@ -3,12 +3,8 @@
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
use Pfatt\Commands\Monitor; use Pfatt\PfattKernel;
use Pfatt\Commands\Startup;
use Symfony\Component\Console\Application;
$application = new Application(); (new PfattKernel())
$application->add(new Monitor()); ->create()
$application->add(new Startup()); ->run();
$application->run();

View file

@ -1,6 +1,7 @@
{ {
"output" : "build/pfatt.phar", "output" : "build/pfatt.phar",
"files": [ "files": [
"bin/pfatt" "bin/pfatt",
"cache/container.php"
] ]
} }

2
cache/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -18,6 +18,7 @@
"php": ">=7.4", "php": ">=7.4",
"psr/log": "^1.1", "psr/log": "^1.1",
"symfony/console": "^5.4", "symfony/console": "^5.4",
"symfony/dependency-injection": "^5.4",
"symfony/process": "^5.4" "symfony/process": "^5.4"
}, },
"require-dev": { "require-dev": {

View file

@ -4,12 +4,11 @@ declare(strict_types=1);
namespace Pfatt\Commands; namespace Pfatt\Commands;
use Pfatt\Config; use Pfatt\Service\Config;
use Pfatt\Logger; use Pfatt\Service\Logger;
use Pfatt\NgController; use Pfatt\Service\NgController;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Logger\ConsoleLogger;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
@ -21,12 +20,15 @@ final class Monitor extends Command
protected Logger $logger; protected Logger $logger;
protected NgController $ngControl; protected NgController $ngControl;
protected function configure(): void public function __construct(
{ Config $config,
// @todo Inject these. Maybe with a factory or container. Logger $logger,
$this->config = new Config('', '', ''); NgController $ngControl
$this->logger = new Logger('pfatt-5268AC'); ) {
$this->ngControl = new NgController($this->logger); parent::__construct('monitor');
$this->config = $config;
$this->logger = $logger;
$this->ngControl = $ngControl;
} }
/** /**

View file

@ -4,9 +4,9 @@ declare(strict_types=1);
namespace Pfatt\Commands; namespace Pfatt\Commands;
use Pfatt\Config; use Pfatt\Service\Config;
use Pfatt\Logger; use Pfatt\Service\Logger;
use Pfatt\NgController; use Pfatt\Service\NgController;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -20,20 +20,26 @@ final class Startup extends Command
protected Logger $logger; protected Logger $logger;
protected NgController $ngControl; protected NgController $ngControl;
protected function configure(): void public function __construct(
{ Config $config,
// @todo Inject these. Maybe with a factory or container. Logger $logger,
$this->config = new Config('', '', ''); NgController $ngControl
$this->logger = new Logger('pfatt'); ) {
$this->ngControl = new NgController($this->logger); parent::__construct('startup');
$this->config = $config;
$this->logger = $logger;
$this->ngControl = $ngControl;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(
{ InputInterface $input,
OutputInterface $output
): int {
$this->logger->setOutput($output);
switch ($this->getVeriant()) { switch ($this->getVeriant()) {
case 'opnsense': case 'opnsense':
$kldload = function (string $mod): Process { $kldload = function (string $mod): Process {
@ -53,7 +59,11 @@ final class Startup extends Command
case 'pfsense': case 'pfsense':
default: default:
$attach = function (string $interface): Process { $attach = function (string $interface): Process {
return new Process(['/usr/local/bin/php', '-r', '"pfSense_ngctl_attach(\'.\', \'' . $interface . '\';"']); return new Process([
'/usr/local/bin/php',
'-r',
'"pfSense_ngctl_attach(\'.\', \'' . $interface . '\';"'
]);
}; };
$this->logger->info('attaching interfaces to ng_ether...'); $this->logger->info('attaching interfaces to ng_ether...');
@ -73,7 +83,9 @@ final class Startup extends Command
/** /**
* @return string * @return string
*/ */
private function getVeriant(): string { private function getVeriant(): string
{
// @todo detect the variant to trigger different behaviors.
return 'opnsense'; return 'opnsense';
} }
} }

11
src/PfattApplication.php Normal file
View file

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Pfatt;
use Symfony\Component\Console\Application;
final class PfattApplication extends Application
{
}

94
src/PfattKernel.php Normal file
View file

@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace Pfatt;
use Pfatt\Commands\Monitor;
use Pfatt\Commands\Startup;
use Pfatt\Service\Config;
use Pfatt\Service\Logger;
use Pfatt\Service\NgController;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\Reference;
final class PfattKernel
{
/**
* @var string[]
*/
private $commands = [
'monitor' => Monitor::class,
'startup' => Startup::class,
];
public function create(): Application
{
// Lazy load command with container
$container = $this->getContainer();
/** @var \Pfatt\PfattApplication $application */
$application = $container->get(PfattApplication::class);
return $application;
}
public function getContainer(): ContainerInterface
{
$file = __DIR__ . '/../cache/container.php';
if (!file_exists($file)) {
$containerBuilder = new ContainerBuilder();
$containerBuilder->register(Logger::class, Logger::class)
->setPublic(true);
$containerBuilder->setAlias(LoggerInterface::class, Logger::class);
$containerBuilder->register('logger-5268', Logger::class)
->setPublic(true)
->setArgument('$channel', 'pfatt-5268AC');
$containerBuilder->register(Config::class, Config::class)
->setPublic(true)
->setArguments(['', '', '']);
$containerBuilder->autowire(NgController::class, NgController::class)
->setPublic(true);
$containerBuilder->autowire(Monitor::class, Monitor::class)
->setPublic(true)
->setArgument(Logger::class, new Reference('logger-5268'));
$containerBuilder->autowire(Startup::class, Startup::class)
->setPublic(true);
$containerBuilder->register(ContainerCommandLoader::class, ContainerCommandLoader::class)
->setArguments([
new Reference('service_container'),
$this->commands
])
->setPublic(true);
$containerBuilder->register(PfattApplication::class, PfattApplication::class)
->setArguments(['PfATT'])
->addMethodCall('setCommandLoader', [new Reference(ContainerCommandLoader::class)])
->setPublic(true);
$containerBuilder->compile();
$dumper = new PhpDumper($containerBuilder);
/**
* This will always be a string because of the default options.
* @psalm-suppress MixedArgumentTypeCoercion
*/
file_put_contents($file, $dumper->dump());
}
require_once $file;
/**
* Tell static analysis of this dynamic class.
* @var \Symfony\Component\DependencyInjection\ContainerInterface $container
* @psalm-suppress UndefinedClass
* @phpstan-ignore-next-line
*/
$container = new \ProjectServiceContainer();
return $container;
}
}

View file

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Pfatt; namespace Pfatt\Service;
/** /**
* Config wrapper. * Config wrapper.

View file

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Pfatt; namespace Pfatt\Service;
use Psr\Log\AbstractLogger; use Psr\Log\AbstractLogger;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -20,7 +20,7 @@ class Logger extends AbstractLogger
*/ */
private ?LoggerInterface $logger; private ?LoggerInterface $logger;
public function __construct(string $channel, LoggerInterface $logger = null) public function __construct(string $channel = 'pfatt', LoggerInterface $logger = null)
{ {
$this->channel = $channel; $this->channel = $channel;
$this->logger = $logger; $this->logger = $logger;

View file

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Pfatt; namespace Pfatt\Service;
use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;