Completed
Push — master ( 3c24ea...404feb )
by Sam
02:45
created

TvheadendStatusManagerCommand::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 47
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 14
Bugs 1 Features 3
Metric Value
c 14
b 1
f 3
dl 0
loc 47
ccs 0
cts 33
cp 0
rs 9.0303
cc 1
eloc 29
nc 1
nop 2
crap 2
1
<?php
2
3
namespace Jalle19\StatusManager\Console\Commands;
4
5
use Auryn\Injector;
6
use Bramus\Monolog\Formatter\ColoredLineFormatter;
7
use Jalle19\StatusManager\Configuration\Configuration;
8
use Jalle19\StatusManager\Configuration\Parser as ConfigurationParser;
9
use Jalle19\StatusManager\Event\Events;
10
use Monolog\Handler\StreamHandler;
11
use Monolog\Logger;
12
use Monolog\Processor\PsrLogMessageProcessor;
13
use Propel\Runtime\Connection\ConnectionManagerSingle;
14
use Propel\Runtime\Propel;
15
use Propel\Runtime\ServiceContainer\StandardServiceContainer;
16
use Psr\Log\LoggerInterface;
17
use React\EventLoop\Factory as EventLoopFactory;
18
use Symfony\Bridge\Monolog\Handler\ConsoleHandler;
19
use Symfony\Component\Console\Command\Command;
20
use Symfony\Component\Console\Input\InputArgument;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Input\InputOption;
23
use Symfony\Component\Console\Output\OutputInterface;
24
use Symfony\Component\EventDispatcher\EventDispatcher;
25
26
/**
27
 * Class TvheadendStatusManagerCommand
28
 * @package   Jalle19\StatusManager\Console\Command
29
 * @copyright Copyright &copy; Sam Stenvall 2015-
30
 * @license   https://www.gnu.org/licenses/gpl.html The GNU General Public License v2.0
31
 */
32
class TvheadendStatusManagerCommand extends Command
33
{
34
35
	const COMMAND_NAME = 'tvheadend-status-manager';
36
37
38
	/**
39
	 * @inheritdoc
40
	 */
41
	protected function configure()
42
	{
43
		$this->setName(self::COMMAND_NAME);
44
		$this->setDescription('Aggregating status manager for tvheadend instances');
45
46
		// Add arguments
47
		$this->addArgument('configFile', InputArgument::REQUIRED, 'The path to the configuration file');
48
		$this->addArgument('databaseFile', InputArgument::REQUIRED, 'The path to the database');
49
		$this->addArgument('logFile', InputArgument::OPTIONAL, 'The path to the log file');
50
51
		// Add options
52
		$this->addOption('updateInterval', 'i', InputOption::VALUE_REQUIRED, 'The status update interval (in seconds)',
53
			Configuration::DEFAULT_UPDATE_INTERVAL);
54
55
		$this->addOption('listenAddress', 'l', InputOption::VALUE_REQUIRED,
56
			'The address the Websocket server should be listening on',
57
			Configuration::DEFAULT_LISTEN_ADDRESS);
58
59
		$this->addOption('listenPort', 'p', InputOption::VALUE_REQUIRED,
60
			'The port the Websocket server should be listening on', Configuration::DEFAULT_LISTEN_PORT);
61
	}
62
63
64
	/**
65
	 * @inheritdoc
66
	 */
67
	protected function execute(InputInterface $input, OutputInterface $output)
68
	{
69
		// Configure Propel and the logger
70
		$configuration = ConfigurationParser::parseConfiguration($input);
71
		$logger        = $this->configureLogger($output, $configuration);
72
		$this->configurePropel($configuration, $logger);
73
74
		$injector = new Injector();
75
76
		// Configure shared instances
77
		$eventLoop       = EventLoopFactory::create();
78
		$eventDispatcher = new EventDispatcher();
79
		$aliases         = [':logger' => $logger, ':loop' => $eventLoop];
80
81
		$injector->share($configuration)
82
		         ->share($logger)
83
		         ->share($eventDispatcher)
84
		         ->share($eventLoop);
85
86
		// Create managers
87
		$statusManager        = $injector->make('Jalle19\StatusManager\Manager\StatusManager', $aliases);
88
		$instanceStateManager = $injector->make('Jalle19\StatusManager\Manager\InstanceStateManager', $aliases);
89
		$webSocketManager     = $injector->make('Jalle19\StatusManager\Manager\WebSocketManager', $aliases);
90
		$persistenceManager   = $injector->make('Jalle19\StatusManager\Manager\PersistenceManager', $aliases);
91
		$statisticsManager    = $injector->make('Jalle19\StatusManager\Manager\StatisticsManager', $aliases);
92
		$inputErrorManager    = $injector->make('Jalle19\StatusManager\Manager\InputErrorManager', $aliases);
93
94
		// Wire the event dispatcher
95
		$webSocketManager->registerMessageHandler($statisticsManager);
96
		$webSocketManager->registerMessageHandler($webSocketManager);
97
		
98
		$eventDispatcher->addSubscriber($statusManager);
99
		$eventDispatcher->addSubscriber($instanceStateManager);
100
		$eventDispatcher->addSubscriber($webSocketManager);
101
		$eventDispatcher->addSubscriber($persistenceManager);
102
		$eventDispatcher->addSubscriber($inputErrorManager);
103
104
		// Configure the event loop and start the application
105
		$eventLoop->addPeriodicTimer($configuration->getUpdateInterval(), function () use ($eventDispatcher)
106
		{
107
			// Emit an event on each tick
108
			$eventDispatcher->dispatch(Events::MAIN_LOOP_TICK);
109
		});
110
111
		$eventDispatcher->dispatch(Events::MAIN_LOOP_STARTING);
112
		$eventLoop->run();
113
	}
114
115
116
	/**
117
	 * Configures and returns the logger instance
118
	 *
119
	 * @param OutputInterface $output
120
	 * @param Configuration   $configuration
121
	 *
122
	 * @return Logger
123
	 */
124
	private function configureLogger(OutputInterface $output, Configuration $configuration)
125
	{
126
		$consoleHandler = new ConsoleHandler($output);
127
		$consoleHandler->setFormatter(new ColoredLineFormatter(null, "[%datetime%] %level_name%: %message%\n"));
128
129
		$logger = new Logger(self::COMMAND_NAME);
130
		$logger->pushHandler($consoleHandler);
131
		$logger->pushProcessor(new PsrLogMessageProcessor());
132
133
		if ($configuration->getLogPath() !== null)
134
		{
135
			$fileHandler = new StreamHandler($configuration->getLogPath());
136
			$logger->pushHandler($fileHandler);
137
		}
138
139
		return $logger;
140
	}
141
142
143
	/**
144
	 * Configures the database
145
	 *
146
	 * @param Configuration   $configuration
147
	 * @param LoggerInterface $logger
148
	 */
149
	private function configurePropel(Configuration $configuration, LoggerInterface $logger)
150
	{
151
		/* @var StandardServiceContainer $serviceContainer */
152
		$serviceContainer = Propel::getServiceContainer();
153
		$serviceContainer->checkVersion('2.0.0-dev');
154
		$serviceContainer->setAdapterClass('tvheadend_status_manager', 'sqlite');
155
		$manager = new ConnectionManagerSingle();
156
		$manager->setConfiguration([
157
			'classname'  => 'Propel\\Runtime\\Connection\\ConnectionWrapper',
158
			'dsn'        => 'sqlite:' . $configuration->getDatabasePath(),
159
			'user'       => null,
160
			'password'   => '',
161
			'attributes' => [
162
				'ATTR_EMULATE_PREPARES' => false,
163
			],
164
			'settings'   => [
165
				'charset' => 'utf8',
166
				'queries' => [],
167
			],
168
		]);
169
		$manager->setName('tvheadend_status_manager');
170
		$serviceContainer->setConnectionManager('tvheadend_status_manager', $manager);
171
		$serviceContainer->setDefaultDatasource('tvheadend_status_manager');
172
173
		$serviceContainer->setLogger(self::COMMAND_NAME, $logger);
174
	}
175
176
}
177