Refactor the CLI commands.

This commit is contained in:
Buster "Silver Eagle" Neece 2018-05-06 20:57:06 -05:00
parent 94f9eacdd7
commit 1dd322b4fa
23 changed files with 212 additions and 170 deletions

View File

@ -330,6 +330,10 @@ return function (\Slim\Container $di, $settings) {
return $logger;
};
$di[\AzuraCast\Console\Application::class] = function($di) use ($settings) {
return \AzuraCast\Console\Application::create($di, $settings);
};
//
// AzuraCast-specific dependencies
//

View File

@ -0,0 +1,47 @@
<?php
namespace App\Console;
use Slim\Container;
/**
* Class Application
* Wraps the default Symfony console application with a DI-aware wrapper.
*
* @package App\Console
*/
class Application extends \Symfony\Component\Console\Application
{
/** @var Container */
protected $di;
/**
* @param Container $di
*/
public function setContainer(Container $di)
{
$this->di = $di;
}
/**
* @return Container
*/
public function getContainer(): Container
{
return $this->di;
}
/**
* @param $service_name
* @return mixed
* @throws \App\Exception
* @throws \Interop\Container\Exception\ContainerException
*/
public function getService($service_name)
{
if ($this->di->has($service_name)) {
return $this->di->get($service_name);
} else {
throw new \App\Exception(sprintf('Service "%s" not found.', $service_name));
}
}
}

View File

@ -1,19 +1,24 @@
<?php
namespace App\Console\Command;
use Interop\Container\ContainerInterface;
use App\Console\Application;
use Symfony\Component\Console\Command\Command;
abstract class CommandAbstract extends Command
{
/**
* @var ContainerInterface
* Return a Dependency Injection service.
*
* @param $service_name
* @return mixed
* @throws \App\Exception
* @throws \Interop\Container\Exception\ContainerException
*/
protected $di;
public function __construct(ContainerInterface $di, $name = null)
public function get($service_name)
{
$this->di = $di;
parent::__construct($name);
/** @var Application $application */
$application = self::getApplication();
return $application->getService($service_name);
}
}

View File

@ -1,11 +1,10 @@
<?php
namespace App\Console\Command;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class LocaleGenerate extends \App\Console\Command\CommandAbstract
class LocaleGenerate extends CommandAbstract
{
/**
* {@inheritdoc}
@ -37,5 +36,6 @@ class LocaleGenerate extends \App\Console\Command\CommandAbstract
$translations->toPoFile($dest_file);
$output->writeln('Locales generated.');
return 0;
}
}

View File

@ -20,7 +20,7 @@ class LocaleImport extends CommandAbstract
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$app_settings = $this->di->get('app_settings');
$app_settings = $this->get('app_settings');
$locales = $app_settings['locale']['supported'];
$locale_base = APP_INCLUDE_BASE.'/locale';
@ -41,5 +41,6 @@ class LocaleImport extends CommandAbstract
}
$output->writeln('Locales imported.');
return 0;
}
}

View File

@ -0,0 +1,92 @@
<?php
namespace AzuraCast\Console;
use App\Console\Command as AppCommand;
use Doctrine\ORM\EntityManager;
use Slim\Container;
class Application extends \App\Console\Application
{
/**
* Register all CLI commands and return a ready-to-execute CLI runner.
*
* @param Container $di
* @param $settings
* @return Application
*/
public static function create(Container $di, $settings): self
{
/** @var EntityManager $em */
$em = $di[EntityManager::class];
$helperSet = \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
$helperSet->set(new \Symfony\Component\Console\Helper\QuestionHelper, 'dialog');
$cli = new self($settings['name'].' Command Line Tools ('.APP_APPLICATION_ENV.')', \AzuraCast\Version::getVersion());
$cli->setContainer($di);
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
// Doctrine ORM/DBAL
\Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
// Doctrine Migrations
$migrate_config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($em->getConnection());
$migrate_config->setMigrationsTableName('app_migrations');
$migrate_config->setMigrationsDirectory(__DIR__.'/../app/src/Entity/Migration');
$migrate_config->setMigrationsNamespace('Entity\Migration');
$output = new \Symfony\Component\Console\Output\ConsoleOutput;
$migrate_config->setOutputWriter(new \Doctrine\DBAL\Migrations\OutputWriter(function($message) use ($output) {
$output->writeln($message);
}));
$migration_commands = [
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
];
foreach($migration_commands as $cmd) {
$cmd->setMigrationConfiguration($migrate_config);
$cli->add($cmd);
}
// Liquidsoap Internal CLI Commands
$cli->addCommands([
new Command\StreamerAuth,
new Command\NextSong,
new Command\DjOn,
new Command\DjOff,
]);
// Other App-specific Commands
$cli->addCommands([
// Locales
new AppCommand\LocaleGenerate,
new AppCommand\LocaleImport,
// Setup
new Command\MigrateConfig,
new Command\SetupInflux,
new Command\SetupFixtures,
// Maintenance
new Command\ClearCache,
new Command\RestartRadio,
new Command\Sync,
new Command\ReprocessMedia,
new Command\GenerateApiDocs,
new Command\UptimeWait,
// User-side tools
new Command\ResetPassword,
]);
return $cli;
}
}

View File

@ -22,7 +22,7 @@ class ClearCache extends \App\Console\Command\CommandAbstract
protected function execute(InputInterface $input, OutputInterface $output)
{
// Flush route cache.
$app_settings = $this->di->get('settings');
$app_settings = $this->get('settings');
if (!empty($app_settings['routerCacheFile'])) {
@unlink($app_settings['routerCacheFile']);
}
@ -30,36 +30,15 @@ class ClearCache extends \App\Console\Command\CommandAbstract
$output->writeln('Router cache file cleared.');
// Flush all Redis databases
/** @var \Redis $redis */
$redis = $this->di[\Redis::class];
$redis = $this->get(\Redis::class);
for($i = 0; $i < 14; $i++) {
$redis->select($i);
$redis->flushAll();
}
// Flush Doctrine cache.
// /** @var EntityManager $em */
// $em = $this->di->get('em');
// Delete metadata, query and result caches
// $cacheDriver = $em->getConfiguration()->getMetadataCacheImpl();
// $cacheDriver->deleteAll();
//
// $queryCacheDriver = $em->getConfiguration()->getQueryCacheImpl();
// $queryCacheDriver->deleteAll();
//
// $resultCacheDriver = $em->getConfiguration()->getResultCacheImpl();
// $resultCacheDriver->deleteAll();
//
// $output->writeln('Doctrine ORM cache flushed.');
// Flush remainder of local cache object
// $cache = $this->di->get('cache');
// $cache->clean();
$output->writeln('Local cache flushed.');
return 0;
}
}

View File

@ -33,16 +33,16 @@ class DjOff extends \App\Console\Command\CommandAbstract
$station_id = (int)$input->getArgument('station_id');
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$station = $em->getRepository(Entity\Station::class)->find($station_id);
if (!($station instanceof Entity\Station) || !$station->getEnableStreamers()) {
return false;
return 1;
}
/** @var Adapters $adapters */
$adapters = $this->di[Adapters::class];
$adapters = $this->get(Adapters::class);
$adapter = $adapters->getBackendAdapter($station);
@ -51,6 +51,6 @@ class DjOff extends \App\Console\Command\CommandAbstract
}
$output->write('received');
return true;
return 0;
}
}

View File

@ -33,16 +33,16 @@ class DjOn extends \App\Console\Command\CommandAbstract
$station_id = (int)$input->getArgument('station_id');
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$station = $em->getRepository(Entity\Station::class)->find($station_id);
if (!($station instanceof Entity\Station) || !$station->getEnableStreamers()) {
return false;
return 1;
}
/** @var Adapters $adapters */
$adapters = $this->di[Adapters::class];
$adapters = $this->get(Adapters::class);
$adapter = $adapters->getBackendAdapter($station);
@ -51,6 +51,6 @@ class DjOn extends \App\Console\Command\CommandAbstract
}
$output->write('received');
return true;
return 0;
}
}

View File

@ -39,7 +39,8 @@ class GenerateApiDocs extends \App\Console\Command\CommandAbstract
file_put_contents(APP_INCLUDE_STATIC . '/api/swagger.json', $swagger);
return $output->writeln('API documentation updated!');
$output->writeln('API documentation updated!');
return 0;
}
}

View File

@ -67,6 +67,6 @@ class MigrateConfig extends \App\Console\Command\CommandAbstract
file_put_contents($env_path, implode("\n", $ini_data));
$output->writeln('Configuration successfully written.');
return true;
return 0;
}
}

View File

@ -36,7 +36,7 @@ class NextSong extends \App\Console\Command\CommandAbstract
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$station_id = (int)$input->getArgument('station_id');
$station = $em->getRepository(Entity\Station::class)->find($station_id);
@ -49,14 +49,16 @@ class NextSong extends \App\Console\Command\CommandAbstract
$as_autodj = ($input->getArgument('as_autodj') !== 'false');
/** @var Adapters $adapters */
$adapters = $this->di[Adapters::class];
$adapters = $this->get(Adapters::class);
$adapter = $adapters->getBackendAdapter($station);
if ($adapter instanceof Liquidsoap) {
return $output->write($adapter->getNextSong($as_autodj));
$output->write($adapter->getNextSong($as_autodj));
return 0;
}
return $output->write('');
$output->write('');
return 1;
}
}

View File

@ -25,7 +25,7 @@ class ReprocessMedia extends \App\Console\Command\CommandAbstract
$output->writeLn('Reloading all metadata for all media...');
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$stations = $em->getRepository(Entity\Station::class)->findAll();
$song_repo = $em->getRepository(Entity\Song::class);
@ -61,5 +61,7 @@ class ReprocessMedia extends \App\Console\Command\CommandAbstract
$output->writeLn('Station media reprocessed.');
}
return 0;
}
}

View File

@ -29,7 +29,7 @@ class ResetPassword extends \App\Console\Command\CommandAbstract
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$user_email = $input->getArgument('email');
@ -51,10 +51,10 @@ class ResetPassword extends \App\Console\Command\CommandAbstract
' ',
'Set a new password using the web interface.',
]);
return true;
return 0;
} else {
$output->writeln('Account not found.');
return false;
return 1;
}
}
}

View File

@ -26,13 +26,13 @@ class RestartRadio extends \App\Console\Command\CommandAbstract
$output->writeLn('Restarting all radio stations...');
/** @var \Supervisor\Supervisor $supervisor */
$supervisor = $this->di[\Supervisor\Supervisor::class];
$supervisor = $this->get(\Supervisor\Supervisor::class);
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
/** @var Configuration $configuration */
$configuration = $this->di[Configuration::class];
$configuration = $this->get(Configuration::class);
/** @var Station[] $stations */
$stations = $em->getRepository(Station::class)->findAll();
@ -51,5 +51,7 @@ class RestartRadio extends \App\Console\Command\CommandAbstract
$supervisor->startAllProcesses();
$em->flush();
return 0;
}
}

View File

@ -5,6 +5,7 @@ use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@ -28,12 +29,21 @@ class SetupFixtures extends \App\Console\Command\CommandAbstract
$loader->loadFromDirectory(APP_INCLUDE_BASE.'/src/Entity/Fixture');
/** @var EntityManager $em */
$em = $this->di->get(EntityManager::class);
$em = $this->get(EntityManager::class);
$purger = new ORMPurger($em);
$executor = new ORMExecutor($em, $purger);
$executor->execute($loader->getFixtures());
$output->writeln('Fixtures loaded.');
// Restart radio stations
$command = $this->getApplication()->find('azuracast:radio:restart');
$command_args = new ArrayInput([
'command' => 'azuracast:radio:restart',
]);
$command->run($command_args, $output);
return 0;
}
}

View File

@ -22,7 +22,7 @@ class SetupInflux extends \App\Console\Command\CommandAbstract
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var Database $influxdb */
$influxdb = $this->di->get(Database::class);
$influxdb = $this->get(Database::class);
$db_name = $influxdb->getName();
@ -102,5 +102,6 @@ class SetupInflux extends \App\Console\Command\CommandAbstract
}
$output->writeln('InfluxDB databases created.');
return 0;
}
}

View File

@ -44,7 +44,7 @@ class StreamerAuth extends \App\Console\Command\CommandAbstract
$station_id = (int)$input->getArgument('station_id');
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$station = $em->getRepository(Entity\Station::class)->find($station_id);

View File

@ -29,7 +29,7 @@ class Sync extends \App\Console\Command\CommandAbstract
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var AzuraCast\Sync $sync */
$sync = $this->di[AzuraCast\Sync::class];
$sync = $this->get(AzuraCast\Sync::class);
switch ($input->getArgument('task')) {
case 'long':
@ -58,5 +58,7 @@ class Sync extends \App\Console\Command\CommandAbstract
$sync->syncNowplaying();
break;
}
return 0;
}
}

View File

@ -48,7 +48,7 @@ class UptimeWait extends \App\Console\Command\CommandAbstract
default:
/** @var EntityManager $em */
$em = $this->di[EntityManager::class];
$em = $this->get(EntityManager::class);
$conn = $em->getConnection();
@ -58,7 +58,7 @@ class UptimeWait extends \App\Console\Command\CommandAbstract
try {
$conn->connect();
$output->writeln('Successfully connected');
exit(0);
return 0;
} catch(\Exception $e) {
$output->writeln($e->getMessage());
sleep($sleep_time);
@ -66,7 +66,7 @@ class UptimeWait extends \App\Console\Command\CommandAbstract
}
}
exit(1);
return 1;
break;
}

View File

@ -1,28 +0,0 @@
#!/usr/bin/env bash
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf > /dev/null
echo "nameserver 8.8.8.8" | sudo tee /etc/resolvconf/resolv.conf.d/base > /dev/null
# Add Vagrant user to the sudoers group
echo 'ubuntu ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
# Set up swap partition
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile none swap sw 0 0" >> /etc/fstab
sudo apt-get update
sudo apt-get install -q -y software-properties-common
sudo add-apt-repository -y ppa:ansible/ansible
sudo apt-get update
sudo apt-get install -q -y python2.7 python-pip python-mysqldb ansible
cat > $HOME/.ansible.cfg <<EOF
[defaults]
remote_tmp = /var/azuracast/www/ansible/tmp
log_path = /var/azuracast/www/ansible/ansible.log
EOF

View File

@ -11,80 +11,6 @@ $di->get('app');
$translator = new \Gettext\Translator();
$translator->register();
/** @var \Doctrine\ORM\EntityManager $em */
$em = $di[\Doctrine\ORM\EntityManager::class];
$db = $em->getConnection();
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($db),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em),
'dialog' => new \Symfony\Component\Console\Helper\QuestionHelper(),
));
$settings = $di['app_settings'];
$cli = new \Symfony\Component\Console\Application($settings['name'].' Command Line Tools ('.APP_APPLICATION_ENV.')', \AzuraCast\Version::getVersion());
$cli->setCatchExceptions(true);
$cli->setHelperSet($helperSet);
\Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
// Migrations commands
$migrate_config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($db);
$migrate_config->setMigrationsTableName('app_migrations');
$migrate_config->setMigrationsDirectory(__DIR__.'/../app/src/Entity/Migration');
$migrate_config->setMigrationsNamespace('Entity\Migration');
$output = new \Symfony\Component\Console\Output\ConsoleOutput;
$migrate_config->setOutputWriter(new \Doctrine\DBAL\Migrations\OutputWriter(function($message) use ($output) {
$output->writeln($message);
}));
$migration_commands = [
new \Doctrine\DBAL\Migrations\Tools\Console\Command\DiffCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\ExecuteCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\GenerateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\MigrateCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\StatusCommand(),
new \Doctrine\DBAL\Migrations\Tools\Console\Command\VersionCommand()
];
foreach($migration_commands as $cmd)
$cmd->setMigrationConfiguration($migrate_config);
$cli->addCommands($migration_commands);
// Liquidsoap internal commands
$cli->addCommands([
new \AzuraCast\Console\Command\StreamerAuth($di),
new \AzuraCast\Console\Command\NextSong($di),
new \AzuraCast\Console\Command\DjOn($di),
new \AzuraCast\Console\Command\DjOff($di),
]);
// Other app-specific commands
$cli->addCommands([
// Locales
new \App\Console\Command\LocaleGenerate($di),
new \App\Console\Command\LocaleImport($di),
// Setup
new \AzuraCast\Console\Command\MigrateConfig($di),
new \AzuraCast\Console\Command\SetupInflux($di),
new \AzuraCast\Console\Command\SetupFixtures($di),
// Maintenance
new \AzuraCast\Console\Command\ClearCache($di),
new \AzuraCast\Console\Command\RestartRadio($di),
new \AzuraCast\Console\Command\Sync($di),
new \AzuraCast\Console\Command\ReprocessMedia($di),
new \AzuraCast\Console\Command\GenerateApiDocs($di),
new \AzuraCast\Console\Command\UptimeWait($di),
// User-side tools
new \AzuraCast\Console\Command\ResetPassword($di),
]);
/** @var \AzuraCast\Console\Application $cli */
$cli = $di[\AzuraCast\Console\Application::class];
$cli->run();

View File

@ -1,4 +0,0 @@
DROP USER 'root'@'localhost';
CREATE USER 'root'@'localhost' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;