Completed
Push — master ( 3dfec0...098987 )
by Sam
03:00
created

TvheadendStatusManagerCommand::execute()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 11
Bugs 1 Features 2
Metric Value
c 11
b 1
f 2
dl 0
loc 38
rs 8.8571
cc 1
eloc 25
nc 1
nop 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
93
		// Wire the event dispatcher
94
		$webSocketManager->registerMessageHandler($statisticsManager);
95
		$eventDispatcher->addSubscriber($statusManager);
96
		$eventDispatcher->addSubscriber($instanceStateManager);
97
		$eventDispatcher->addSubscriber($webSocketManager);
98
		$eventDispatcher->addSubscriber($persistenceManager);
99
100
		// Configure the event loop and start the application
101
		$eventLoop->addPeriodicTimer($configuration->getUpdateInterval(), [$statusManager, 'requestInstances']);
1 ignored issue
show
Documentation introduced by
$configuration->getUpdateInterval() is of type double, but the function expects a object<React\EventLoop\numeric>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
102
		$eventDispatcher->dispatch(Events::MAIN_LOOP_STARTING);
103
		$eventLoop->run();
104
	}
105
106
107
	/**
108
	 * Configures and returns the logger instance
109
	 *
110
	 * @param OutputInterface $output
111
	 * @param Configuration   $configuration
112
	 *
113
	 * @return Logger
114
	 */
115
	private function configureLogger(OutputInterface $output, Configuration $configuration)
116
	{
117
		$consoleHandler = new ConsoleHandler($output);
118
		$consoleHandler->setFormatter(new ColoredLineFormatter(null, "[%datetime%] %level_name%: %message%\n"));
119
120
		$logger = new Logger(self::COMMAND_NAME);
121
		$logger->pushHandler($consoleHandler);
122
		$logger->pushProcessor(new PsrLogMessageProcessor());
123
124
		if ($configuration->getLogPath() !== null)
125
		{
126
			$fileHandler = new StreamHandler($configuration->getLogPath());
127
			$logger->pushHandler($fileHandler);
128
		}
129
130
		return $logger;
131
	}
132
133
134
	/**
135
	 * Configures the database
136
	 *
137
	 * @param Configuration   $configuration
138
	 * @param LoggerInterface $logger
139
	 */
140
	private function configurePropel(Configuration $configuration, LoggerInterface $logger)
141
	{
142
		/* @var StandardServiceContainer $serviceContainer */
143
		$serviceContainer = Propel::getServiceContainer();
144
		$serviceContainer->checkVersion('2.0.0-dev');
145
		$serviceContainer->setAdapterClass('tvheadend_status_manager', 'sqlite');
146
		$manager = new ConnectionManagerSingle();
147
		$manager->setConfiguration([
148
			'classname'  => 'Propel\\Runtime\\Connection\\ConnectionWrapper',
149
			'dsn'        => 'sqlite:' . $configuration->getDatabasePath(),
150
			'user'       => null,
151
			'password'   => '',
152
			'attributes' => [
153
				'ATTR_EMULATE_PREPARES' => false,
154
			],
155
			'settings'   => [
156
				'charset' => 'utf8',
157
				'queries' => [],
158
			],
159
		]);
160
		$manager->setName('tvheadend_status_manager');
161
		$serviceContainer->setConnectionManager('tvheadend_status_manager', $manager);
162
		$serviceContainer->setDefaultDatasource('tvheadend_status_manager');
163
164
		$serviceContainer->setLogger(self::COMMAND_NAME, $logger);
165
	}
166
167
}
168