Move Settings and Logging to static system-wide functions.

This commit is contained in:
Buster "Silver Eagle" Neece 2019-09-12 00:31:01 -05:00
parent abc9930472
commit daf78fa738
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
69 changed files with 331 additions and 359 deletions

28
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.111.0", "version": "3.111.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "a31376012346118b2b88df6d2f0c185af71e3096" "reference": "5e80d4bec17e197be494af4f38e1fcd17f728138"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a31376012346118b2b88df6d2f0c185af71e3096", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/5e80d4bec17e197be494af4f38e1fcd17f728138",
"reference": "a31376012346118b2b88df6d2f0c185af71e3096", "reference": "5e80d4bec17e197be494af4f38e1fcd17f728138",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -87,7 +87,7 @@
"s3", "s3",
"sdk" "sdk"
], ],
"time": "2019-09-09T18:13:28+00:00" "time": "2019-09-11T18:16:47+00:00"
}, },
{ {
"name": "azuracast/azuracore", "name": "azuracast/azuracore",
@ -95,12 +95,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/AzuraCast/azuracore.git", "url": "https://github.com/AzuraCast/azuracore.git",
"reference": "7fae6fe42c33350d2c16425512450aeac3fa939b" "reference": "3f31357e03e91249c4284d579cf593891e206412"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/AzuraCast/azuracore/zipball/7fae6fe42c33350d2c16425512450aeac3fa939b", "url": "https://api.github.com/repos/AzuraCast/azuracore/zipball/3f31357e03e91249c4284d579cf593891e206412",
"reference": "7fae6fe42c33350d2c16425512450aeac3fa939b", "reference": "3f31357e03e91249c4284d579cf593891e206412",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -154,7 +154,7 @@
} }
], ],
"description": "A lightweight core application framework.", "description": "A lightweight core application framework.",
"time": "2019-09-10T17:41:01+00:00" "time": "2019-09-12T04:10:12+00:00"
}, },
{ {
"name": "azuracast/azuraforms", "name": "azuracast/azuraforms",
@ -3650,16 +3650,16 @@
}, },
{ {
"name": "paragonie/sodium_compat", "name": "paragonie/sodium_compat",
"version": "v1.10.1", "version": "v1.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/paragonie/sodium_compat.git", "url": "https://github.com/paragonie/sodium_compat.git",
"reference": "5115fa44886d1c2785d2f135ef4626db868eac4b" "reference": "fee1b6ea9c83dac7b4a17febf58fb712ada7dd6e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/5115fa44886d1c2785d2f135ef4626db868eac4b", "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/fee1b6ea9c83dac7b4a17febf58fb712ada7dd6e",
"reference": "5115fa44886d1c2785d2f135ef4626db868eac4b", "reference": "fee1b6ea9c83dac7b4a17febf58fb712ada7dd6e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -3728,7 +3728,7 @@
"secret-key cryptography", "secret-key cryptography",
"side-channel resistant" "side-channel resistant"
], ],
"time": "2019-07-12T16:36:59+00:00" "time": "2019-09-11T23:58:35+00:00"
}, },
{ {
"name": "php-di/invoker", "name": "php-di/invoker",

View File

@ -1,4 +1,6 @@
<?php <?php
use App\Settings;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
/** /**
@ -26,7 +28,7 @@ return [
'files' => [ 'files' => [
'js' => [ 'js' => [
[ [
'src' => 'dist/lib/vue/' . (APP_IN_PRODUCTION ? 'vue.min.js' : 'vue.js'), 'src' => 'dist/lib/vue/' . (Settings::getInstance()->isProduction() ? 'vue.min.js' : 'vue.js'),
], ],
], ],
], ],

View File

@ -3,7 +3,7 @@
* PHP-DI Services * PHP-DI Services
*/ */
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Psr\Container\ContainerInterface; use Psr\Container\ContainerInterface;

View File

@ -23,12 +23,5 @@ parameters:
# Supervisor functions that do exist but aren't annotated properly in the connector lib. # Supervisor functions that do exist but aren't annotated properly in the connector lib.
- '#Call to an undefined method Supervisor\\Supervisor::reloadConfig().#' - '#Call to an undefined method Supervisor\\Supervisor::reloadConfig().#'
dynamicConstantNames:
- APP_IS_COMMAND_LINE
- APP_INSIDE_DOCKER
- APP_TESTING_MODE
- APP_APPLICATION_ENV
- APP_IN_PRODUCTION
includes: includes:
- vendor/phpstan/phpstan-doctrine/extension.neon - vendor/phpstan/phpstan-doctrine/extension.neon

View File

@ -7,22 +7,36 @@ use Azura\App;
use Azura\Exception; use Azura\Exception;
use Azura\Http\Factory\ResponseFactory; use Azura\Http\Factory\ResponseFactory;
use Azura\Http\Factory\ServerRequestFactory; use Azura\Http\Factory\ServerRequestFactory;
use Azura\Settings; use Azura\Logger;
use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\Common\Annotations\AnnotationRegistry;
use DI;
use Psr\Log\LoggerInterface;
class AppFactory extends \Azura\AppFactory class AppFactory extends \Azura\AppFactory
{ {
/** /**
* @inheritDoc * @inheritDoc
*/ */
public static function create($autoloader = null, $settings = [], $diDefinitions = []): App public static function create($autoloader = null, $appSettings = [], $diDefinitions = []): App
{ {
// Register Annotation autoloader // Register Annotation autoloader
if (null !== $autoloader) { if (null !== $autoloader) {
AnnotationRegistry::registerLoader([$autoloader, 'loadClass']); AnnotationRegistry::registerLoader([$autoloader, 'loadClass']);
} }
$settings = self::buildSettings($settings); $settings = new Settings(self::buildSettings($appSettings));
Settings::setInstance($settings);
self::applyPhpSettings($settings);
// Helper constants for annotations.
/** @noinspection SummerTimeUnsafeTimeManipulationInspection */
define('SAMPLE_TIMESTAMP', random_int(time() - 86400, time() + 86400));
// Override DI definitions for settings.
$diDefinitions[Settings::class] = $settings;
$diDefinitions[\Azura\Settings::class] = DI\get(Settings::class);
$diDefinitions['settings'] = DI\get(Settings::class);
self::applyPhpSettings($settings); self::applyPhpSettings($settings);
@ -38,6 +52,8 @@ class AppFactory extends \Azura\AppFactory
$di = self::buildContainer($settings, $diDefinitions); $di = self::buildContainer($settings, $diDefinitions);
Logger::setInstance($di->get(LoggerInterface::class));
// Set Response/Request decoratorclasses. // Set Response/Request decoratorclasses.
ServerRequestFactory::setServerRequestClass(ServerRequest::class); ServerRequestFactory::setServerRequestClass(ServerRequest::class);
ResponseFactory::setResponseClass(Response::class); ResponseFactory::setResponseClass(Response::class);
@ -49,15 +65,10 @@ class AppFactory extends \Azura\AppFactory
self::updateRouteHandling($app); self::updateRouteHandling($app);
self::buildRoutes($app); self::buildRoutes($app);
$settings = $di->get(Settings::class);
define('APP_APPLICATION_ENV', $settings[Settings::APP_ENV]);
define('APP_IN_PRODUCTION', $settings->isProduction());
return $app; return $app;
} }
protected static function buildSettings($settings): Settings protected static function buildSettings(array $settings): array
{ {
if (!isset($settings[Settings::BASE_DIR])) { if (!isset($settings[Settings::BASE_DIR])) {
throw new Exception\BootstrapException('No base directory specified!'); throw new Exception\BootstrapException('No base directory specified!');
@ -65,22 +76,11 @@ class AppFactory extends \Azura\AppFactory
$settings[Settings::TEMP_DIR] = dirname($settings[Settings::BASE_DIR]) . '/www_tmp'; $settings[Settings::TEMP_DIR] = dirname($settings[Settings::BASE_DIR]) . '/www_tmp';
// Define the "helper" constants used by AzuraCast. $settings[Settings::IS_DOCKER] = file_exists(dirname($settings[Settings::BASE_DIR]) . '/.docker');
define('APP_IS_COMMAND_LINE', PHP_SAPI === 'cli'); $settings[Settings::DOCKER_REVISION] = getenv('AZURACAST_DC_REVISION') ?? 1;
define('APP_INCLUDE_ROOT', $settings[Settings::BASE_DIR]); $settings[Settings::CONFIG_DIR] = $settings[Settings::BASE_DIR].'/config';
define('APP_INCLUDE_TEMP', $settings[Settings::TEMP_DIR]); $settings[Settings::VIEWS_DIR] = $settings[Settings::BASE_DIR].'/templates';
define('APP_INSIDE_DOCKER', file_exists(dirname($settings[Settings::BASE_DIR]) . '/.docker'));
define('APP_DOCKER_REVISION', getenv('AZURACAST_DC_REVISION') ?? 1);
$settings[Settings::IS_DOCKER] = APP_INSIDE_DOCKER;
define('APP_TESTING_MODE',
(isset($settings[Settings::APP_ENV]) && Settings::ENV_TESTING === $settings[Settings::APP_ENV]));
// Constants used in annotations
define('SAMPLE_TIMESTAMP', rand(time() - 86400, time() + 86400));
return parent::buildSettings($settings); return parent::buildSettings($settings);
} }

View File

@ -7,7 +7,7 @@ use App\Exception\NotLoggedInException;
use Azura\Exception; use Azura\Exception;
use Azura\Session; use Azura\Session;
use Azura\Session\NamespaceInterface; use Azura\Session\NamespaceInterface;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
class Auth class Auth
@ -21,9 +21,6 @@ class Auth
/** @var NamespaceInterface */ /** @var NamespaceInterface */
protected $session_namespace; protected $session_namespace;
/** @var Settings */
protected $settings;
/** @var UserRepository */ /** @var UserRepository */
protected $user_repo; protected $user_repo;
@ -36,19 +33,15 @@ class Auth
/** /**
* @param Session $session * @param Session $session
* @param EntityManager $em * @param EntityManager $em
* @param Settings $settings
*/ */
public function __construct( public function __construct(
Session $session, Session $session,
EntityManager $em, EntityManager $em
Settings $settings
) { ) {
$this->user_repo = $em->getRepository(User::class); $this->user_repo = $em->getRepository(User::class);
$this->session = $session; $this->session = $session;
$this->session_namespace = $this->session->get('auth'); $this->session_namespace = $this->session->get('auth');
$this->settings = $settings;
} }
/** /**
@ -134,7 +127,7 @@ class Auth
*/ */
public function isLoggedIn(): bool public function isLoggedIn(): bool
{ {
if (APP_IS_COMMAND_LINE && !APP_TESTING_MODE) { if (Settings::getInstance()->isCli() && !Settings::getInstance()->isTesting()) {
return false; return false;
} }

View File

@ -3,7 +3,7 @@ namespace App\Console\Command;
use App\Version; use App\Version;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;

View File

@ -2,7 +2,7 @@
namespace App\Console\Command; namespace App\Console\Command;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Gettext\Translations; use Gettext\Translations;
use RecursiveDirectoryIterator; use RecursiveDirectoryIterator;
use RecursiveIteratorIterator; use RecursiveIteratorIterator;

View File

@ -2,7 +2,7 @@
namespace App\Console\Command; namespace App\Console\Command;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Gettext\Translations; use Gettext\Translations;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;

View File

@ -2,7 +2,7 @@
namespace App\Console\Command; namespace App\Console\Command;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;

View File

@ -4,7 +4,7 @@ namespace App\Console\Command;
use App\Entity; use App\Entity;
use App\Service\AzuraCastCentral; use App\Service\AzuraCastCentral;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;

View File

@ -3,7 +3,7 @@ namespace App\Console\Command;
use App\Entity\Station; use App\Entity\Station;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use Cake\Chronos\Chronos; use Cake\Chronos\Chronos;
use Doctrine\Common\DataFixtures\Executor\ORMExecutor; use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
use Doctrine\Common\DataFixtures\Loader; use Doctrine\Common\DataFixtures\Loader;

View File

@ -2,7 +2,7 @@
namespace App\Console\Command; namespace App\Console\Command;
use Azura\Console\Command\CommandAbstract; use Azura\Console\Command\CommandAbstract;
use Azura\Settings; use App\Settings;
use InfluxDB\Database; use InfluxDB\Database;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;

View File

@ -5,7 +5,7 @@ use App\Form\SettingsForm;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use Azura\Config; use Azura\Config;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;

View File

@ -6,6 +6,7 @@ use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\Quota; use App\Radio\Quota;
use App\Sync\Runner; use App\Sync\Runner;
use App\Settings;
use Brick\Math\BigInteger; use Brick\Math\BigInteger;
use Monolog\Handler\TestHandler; use Monolog\Handler\TestHandler;
use Monolog\Logger; use Monolog\Logger;
@ -54,7 +55,7 @@ class IndexController
]); ]);
} }
$stations_base_dir = dirname(APP_INCLUDE_ROOT) . '/stations'; $stations_base_dir = Settings::getInstance()->getStationDirectory();
$space_total = BigInteger::of(disk_total_space($stations_base_dir)); $space_total = BigInteger::of(disk_total_space($stations_base_dir));
$space_free = BigInteger::of(disk_free_space($stations_base_dir)); $space_free = BigInteger::of(disk_free_space($stations_base_dir));

View File

@ -6,6 +6,7 @@ use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\Frontend\SHOUTcast; use App\Radio\Frontend\SHOUTcast;
use Azura\Config; use Azura\Config;
use App\Settings;
use Exception; use Exception;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
@ -40,7 +41,7 @@ class InstallShoutcastController
if ('POST' === $request->getMethod() && $form->isValid($_POST)) { if ('POST' === $request->getMethod() && $form->isValid($_POST)) {
try { try {
$sc_base_dir = dirname(APP_INCLUDE_ROOT) . '/servers/shoutcast2'; $sc_base_dir = Settings::getInstance()->getParentDirectory() . '/servers/shoutcast2';
$files = $request->getUploadedFiles(); $files = $request->getUploadedFiles();
/** @var UploadedFileInterface $import_file */ /** @var UploadedFileInterface $import_file */

View File

@ -5,6 +5,7 @@ use App\Controller\Traits\LogViewerTrait;
use App\Entity; use App\Entity;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Settings;
use Azura\Exception; use Azura\Exception;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -45,38 +46,39 @@ class LogsController
protected function _getGlobalLogs(): array protected function _getGlobalLogs(): array
{ {
$log_paths = []; $tempDir = Settings::getInstance()->getTempDirectory();
$logPaths = [];
$log_paths['azuracast_log'] = [ $logPaths['azuracast_log'] = [
'name' => __('AzuraCast Application Log'), 'name' => __('AzuraCast Application Log'),
'path' => APP_INCLUDE_TEMP . '/app.log', 'path' => $tempDir . '/app.log',
'tail' => true, 'tail' => true,
]; ];
if (!APP_INSIDE_DOCKER) { if (!Settings::getInstance()->isDocker()) {
$log_paths['nginx_access'] = [ $logPaths['nginx_access'] = [
'name' => __('Nginx Access Log'), 'name' => __('Nginx Access Log'),
'path' => APP_INCLUDE_TEMP . '/access.log', 'path' => $tempDir . '/access.log',
'tail' => true, 'tail' => true,
]; ];
$log_paths['nginx_error'] = [ $logPaths['nginx_error'] = [
'name' => __('Nginx Error Log'), 'name' => __('Nginx Error Log'),
'path' => APP_INCLUDE_TEMP . '/error.log', 'path' => $tempDir . '/error.log',
'tail' => true, 'tail' => true,
]; ];
$log_paths['php'] = [ $logPaths['php'] = [
'name' => __('PHP Application Log'), 'name' => __('PHP Application Log'),
'path' => APP_INCLUDE_TEMP . '/php_errors.log', 'path' => $tempDir . '/php_errors.log',
'tail' => true, 'tail' => true,
]; ];
$log_paths['supervisord'] = [ $logPaths['supervisord'] = [
'name' => __('Supervisord Log'), 'name' => __('Supervisord Log'),
'path' => APP_INCLUDE_TEMP . '/supervisord.log', 'path' => $tempDir . '/supervisord.log',
'tail' => true, 'tail' => true,
]; ];
} }
return $log_paths; return $logPaths;
} }
public function viewAction(ServerRequest $request, Response $response, $station_id, $log): ResponseInterface public function viewAction(ServerRequest $request, Response $response, $station_id, $log): ResponseInterface

View File

@ -4,7 +4,7 @@ namespace App\Controller\Api;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Version; use App\Version;
use Azura\Settings; use App\Settings;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use function OpenApi\scan; use function OpenApi\scan;

View File

@ -7,7 +7,7 @@ use App\Form\Form;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use Azura\Config; use Azura\Config;
use Azura\Settings; use App\Settings;
use AzuraForms\Field\AbstractField; use AzuraForms\Field\AbstractField;
use BaconQrCode; use BaconQrCode;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;

View File

@ -9,6 +9,7 @@ use App\Form\Form;
use App\Form\StationForm; use App\Form\StationForm;
use App\Http\Response; use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Settings;
use Azura\Config; use Azura\Config;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
@ -30,25 +31,31 @@ class SetupController
/** @var array */ /** @var array */
protected $settings_form_config; protected $settings_form_config;
/** @var Settings */
protected $settings;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Auth $auth * @param Auth $auth
* @param Acl $acl * @param Acl $acl
* @param StationForm $station_form * @param StationForm $station_form
* @param Config $config * @param Config $config
* @param Settings $settings
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Auth $auth, Auth $auth,
Acl $acl, Acl $acl,
StationForm $station_form, StationForm $station_form,
Config $config Config $config,
Settings $settings
) { ) {
$this->em = $em; $this->em = $em;
$this->auth = $auth; $this->auth = $auth;
$this->acl = $acl; $this->acl = $acl;
$this->station_form = $station_form; $this->station_form = $station_form;
$this->settings_form_config = $config->get('forms/settings'); $this->settings_form_config = $config->get('forms/settings');
$this->settings = $settings;
} }
/** /**
@ -126,7 +133,7 @@ class SetupController
{ {
// Verify current step. // Verify current step.
$current_step = $this->_getSetupStep(); $current_step = $this->_getSetupStep();
if ($current_step !== 'register' && APP_IN_PRODUCTION) { if ($current_step !== 'register' && $this->settings->isProduction()) {
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step)); return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
} }
@ -179,7 +186,7 @@ class SetupController
{ {
// Verify current step. // Verify current step.
$current_step = $this->_getSetupStep(); $current_step = $this->_getSetupStep();
if ($current_step !== 'station' && APP_IN_PRODUCTION) { if ($current_step !== 'station' && $this->settings->isProduction()) {
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step)); return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
} }
@ -204,7 +211,7 @@ class SetupController
{ {
// Verify current step. // Verify current step.
$current_step = $this->_getSetupStep(); $current_step = $this->_getSetupStep();
if ($current_step !== 'settings' && APP_IN_PRODUCTION) { if ($current_step !== 'settings' && $this->settings->isProduction()) {
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step)); return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
} }

View File

@ -6,7 +6,7 @@ use App\Http\Response;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Sync\Task\RadioAutomation; use App\Sync\Task\RadioAutomation;
use Azura\Config; use Azura\Config;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Exception; use Exception;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;

View File

@ -3,7 +3,6 @@ namespace App;
use App\Entity; use App\Entity;
use App\Service\NChan; use App\Service\NChan;
use Azura\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Gettext\Translator; use Gettext\Translator;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
@ -18,33 +17,21 @@ class Customization
public const DEFAULT_LOCALE = 'en_US.UTF-8'; public const DEFAULT_LOCALE = 'en_US.UTF-8';
public const DEFAULT_THEME = 'light'; public const DEFAULT_THEME = 'light';
/** @var Settings */
protected $app_settings;
/** @var Entity\User|null */ /** @var Entity\User|null */
protected $user; protected $user;
/** @var Entity\Repository\SettingsRepository */ /** @var Entity\Repository\SettingsRepository */
protected $settings_repo; protected $settingsRepo;
/** @var string|null */ /** @var string|null */
protected $locale; protected $locale;
public function __construct(Settings $app_settings, EntityManager $em) public function __construct(EntityManager $em)
{ {
/** @var Entity\Repository\SettingsRepository $settings_repo */ /** @var Entity\Repository\SettingsRepository $settings_repo */
$settings_repo = $em->getRepository(Entity\Settings::class); $settings_repo = $em->getRepository(Entity\Settings::class);
$this->app_settings = $app_settings; $this->settingsRepo = $settings_repo;
$this->settings_repo = $settings_repo;
}
/**
* @param null $locale
*/
public static function setGlobalValues($locale = null): void
{
} }
/** /**
@ -70,7 +57,7 @@ class Customization
// Set up the PHP translator // Set up the PHP translator
$translator = new Translator(); $translator = new Translator();
$locale_base = $this->app_settings[Settings::BASE_DIR] . '/resources/locale/compiled'; $locale_base = Settings::getInstance()->getBaseDirectory() . '/resources/locale/compiled';
$locale_path = $locale_base . '/' . $this->locale . '.php'; $locale_path = $locale_base . '/' . $this->locale . '.php';
if (file_exists($locale_path)) { if (file_exists($locale_path)) {
@ -98,11 +85,12 @@ class Customization
*/ */
protected function initLocale(?Request $request = null): ?string protected function initLocale(?Request $request = null): ?string
{ {
if ($this->app_settings->isTesting()) { $settings = Settings::getInstance();
if ($settings->isTesting()) {
return self::DEFAULT_LOCALE; return self::DEFAULT_LOCALE;
} }
$supported_locales = $this->app_settings['locale']['supported']; $supported_locales = $settings['locale']['supported'];
$try_locales = []; $try_locales = [];
// Prefer user-based profile locale. // Prefer user-based profile locale.
@ -176,7 +164,7 @@ class Customization
static $instance_name; static $instance_name;
if ($instance_name === null) { if ($instance_name === null) {
$instance_name = $this->settings_repo->getSetting(Entity\Settings::INSTANCE_NAME, ''); $instance_name = $this->settingsRepo->getSetting(Entity\Settings::INSTANCE_NAME, '');
} }
return $instance_name; return $instance_name;
@ -189,7 +177,7 @@ class Customization
*/ */
public function getPublicTheme(): string public function getPublicTheme(): string
{ {
return $this->settings_repo->getSetting(Entity\Settings::PUBLIC_THEME, self::DEFAULT_THEME); return $this->settingsRepo->getSetting(Entity\Settings::PUBLIC_THEME, self::DEFAULT_THEME);
} }
/** /**
@ -199,7 +187,7 @@ class Customization
*/ */
public function getCustomPublicCss() public function getCustomPublicCss()
{ {
return (string)$this->settings_repo->getSetting(Entity\Settings::CUSTOM_CSS_PUBLIC, ''); return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_CSS_PUBLIC, '');
} }
/** /**
@ -209,7 +197,7 @@ class Customization
*/ */
public function getCustomPublicJs() public function getCustomPublicJs()
{ {
return (string)$this->settings_repo->getSetting(Entity\Settings::CUSTOM_JS_PUBLIC, ''); return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_JS_PUBLIC, '');
} }
/** /**
@ -219,7 +207,7 @@ class Customization
*/ */
public function getCustomInternalCss() public function getCustomInternalCss()
{ {
return (string)$this->settings_repo->getSetting(Entity\Settings::CUSTOM_CSS_INTERNAL, ''); return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_CSS_INTERNAL, '');
} }
/** /**
@ -229,7 +217,7 @@ class Customization
*/ */
public function hideAlbumArt(): bool public function hideAlbumArt(): bool
{ {
return (bool)$this->settings_repo->getSetting(Entity\Settings::HIDE_ALBUM_ART, false); return (bool)$this->settingsRepo->getSetting(Entity\Settings::HIDE_ALBUM_ART, false);
} }
/** /**
@ -239,7 +227,7 @@ class Customization
*/ */
public function getDefaultAlbumArtUrl(): UriInterface public function getDefaultAlbumArtUrl(): UriInterface
{ {
$custom_url = trim($this->settings_repo->getSetting(Entity\Settings::DEFAULT_ALBUM_ART_URL)); $custom_url = trim($this->settingsRepo->getSetting(Entity\Settings::DEFAULT_ALBUM_ART_URL));
if (!empty($custom_url)) { if (!empty($custom_url)) {
return new Uri($custom_url); return new Uri($custom_url);
@ -256,16 +244,18 @@ class Customization
*/ */
public function getPageTitle($title = null): string public function getPageTitle($title = null): string
{ {
$settings = Settings::getInstance();
if (!$this->hideProductName()) { if (!$this->hideProductName()) {
if ($title) { if ($title) {
$title .= ' - ' . $this->app_settings[Settings::APP_NAME]; $title .= ' - ' . $settings[Settings::APP_NAME];
} else { } else {
$title = $this->app_settings[Settings::APP_NAME]; $title = $settings[Settings::APP_NAME];
} }
} }
if (!$this->app_settings->isProduction()) { if (!$settings->isProduction()) {
$title = '(' . ucfirst($this->app_settings[Settings::APP_ENV]) . ') ' . $title; $title = '(' . ucfirst($settings[Settings::APP_ENV]) . ') ' . $title;
} }
return $title; return $title;
@ -278,7 +268,7 @@ class Customization
*/ */
public function hideProductName(): bool public function hideProductName(): bool
{ {
return (bool)$this->settings_repo->getSetting(Entity\Settings::HIDE_PRODUCT_NAME, false); return (bool)$this->settingsRepo->getSetting(Entity\Settings::HIDE_PRODUCT_NAME, false);
} }
/** /**
@ -290,7 +280,7 @@ class Customization
return false; return false;
} }
return (bool)$this->settings_repo->getSetting(Entity\Settings::NOWPLAYING_USE_WEBSOCKETS, false); return (bool)$this->settingsRepo->getSetting(Entity\Settings::NOWPLAYING_USE_WEBSOCKETS, false);
} }
} }

View File

@ -5,6 +5,7 @@ use App\Entity;
use App\Radio\Adapters; use App\Radio\Adapters;
use App\Radio\Configuration; use App\Radio\Configuration;
use App\Radio\Frontend\AbstractFrontend; use App\Radio\Frontend\AbstractFrontend;
use App\Settings;
use App\Sync\Task\Media; use App\Sync\Task\Media;
use App\Utilities; use App\Utilities;
use Azura\Doctrine\Repository; use Azura\Doctrine\Repository;
@ -156,7 +157,7 @@ class StationRepository extends Repository
public function create(Entity\Station $station): void public function create(Entity\Station $station): void
{ {
// Create path for station. // Create path for station.
$station_base_dir = dirname(APP_INCLUDE_ROOT) . '/stations'; $station_base_dir = Settings::getInstance()->getStationDirectory();
$station_dir = $station_base_dir . '/' . $station->getShortName(); $station_dir = $station_base_dir . '/' . $station->getShortName();
$station->setRadioBaseDir($station_dir); $station->setRadioBaseDir($station_dir);

View File

@ -3,6 +3,7 @@ namespace App\Form;
use App\Entity\Station; use App\Entity\Station;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Settings;
use Azura\Doctrine\Repository; use Azura\Doctrine\Repository;
use Azura\Exception; use Azura\Exception;
use Azura\Normalizer\DoctrineEntityNormalizer; use Azura\Normalizer\DoctrineEntityNormalizer;
@ -22,9 +23,6 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
*/ */
class EntityForm extends Form class EntityForm extends Form
{ {
/** @var EntityManager */
protected $em;
/** @var Serializer */ /** @var Serializer */
protected $serializer; protected $serializer;
@ -142,7 +140,7 @@ class EntityForm extends Form
$this->em->flush($record); $this->em->flush($record);
// Intentionally refresh the station entity in case it didn't refresh elsewhere. // Intentionally refresh the station entity in case it didn't refresh elsewhere.
if ($this->station instanceof Station && APP_TESTING_MODE) { if ($this->station instanceof Station && Settings::getInstance()->isTesting()) {
$this->em->refresh($this->station); $this->em->refresh($this->station);
} }

View File

@ -34,6 +34,7 @@ class EntityFormManager
$this->em = $em; $this->em = $em;
$this->serializer = $serializer; $this->serializer = $serializer;
$this->validator = $validator; $this->validator = $validator;
$this->custom_forms = $custom_forms; $this->custom_forms = $custom_forms;
} }
@ -43,6 +44,7 @@ class EntityFormManager
* *
* @param string $entity_class * @param string $entity_class
* @param array|null $form_config * @param array|null $form_config
* @param array|null $defaults
* @return EntityForm * @return EntityForm
*/ */
public function getForm($entity_class, array $form_config = null, array $defaults = null): EntityForm public function getForm($entity_class, array $form_config = null, array $defaults = null): EntityForm

View File

@ -3,6 +3,7 @@ namespace App\Form;
use App\Entity; use App\Entity;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Settings;
use Azura\Config; use Azura\Config;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;

View File

@ -5,6 +5,7 @@ use App\Acl;
use App\Entity; use App\Entity;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\Configuration; use App\Radio\Configuration;
use App\Settings;
use App\Sync\Task\Media; use App\Sync\Task\Media;
use Azura\Config; use Azura\Config;
use DeepCopy; use DeepCopy;
@ -23,7 +24,6 @@ class StationCloneForm extends StationForm
protected $media_sync; protected $media_sync;
/** /**
* StationCloneForm constructor.
* @param EntityManager $em * @param EntityManager $em
* @param Serializer $serializer * @param Serializer $serializer
* @param ValidatorInterface $validator * @param ValidatorInterface $validator
@ -168,7 +168,7 @@ class StationCloneForm extends StationForm
} }
// Set new radio base directory // Set new radio base directory
$station_base_dir = dirname(APP_INCLUDE_ROOT) . '/stations'; $station_base_dir = Settings::getInstance()->getStationDirectory();
$new_record->setRadioBaseDir($station_base_dir . '/' . $new_record->getShortName()); $new_record->setRadioBaseDir($station_base_dir . '/' . $new_record->getShortName());
// Persist all newly created records (and relations). // Persist all newly created records (and relations).

View File

@ -5,6 +5,7 @@ use App\Acl;
use App\Entity; use App\Entity;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\Frontend\SHOUTcast; use App\Radio\Frontend\SHOUTcast;
use App\Settings;
use Azura\Config; use Azura\Config;
use Azura\Doctrine\Repository; use Azura\Doctrine\Repository;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;

View File

@ -5,6 +5,7 @@ use App\Entity;
use App\Entity\Station; use App\Entity\Station;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\Adapters; use App\Radio\Adapters;
use App\Settings;
use Azura\Config; use Azura\Config;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;
@ -19,12 +20,14 @@ class StationMountForm extends EntityForm
* @param EntityManager $em * @param EntityManager $em
* @param Serializer $serializer * @param Serializer $serializer
* @param ValidatorInterface $validator * @param ValidatorInterface $validator
* @param Settings $settings
* @param Config $config * @param Config $config
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Serializer $serializer, Serializer $serializer,
ValidatorInterface $validator, ValidatorInterface $validator,
Settings $settings,
Config $config Config $config
) { ) {
$form_configs = [ $form_configs = [
@ -32,7 +35,7 @@ class StationMountForm extends EntityForm
Adapters::FRONTEND_SHOUTCAST => $config->get('forms/mount/shoutcast2'), Adapters::FRONTEND_SHOUTCAST => $config->get('forms/mount/shoutcast2'),
]; ];
parent::__construct($em, $serializer, $validator); parent::__construct($em, $serializer, $validator, $settings);
$this->entityClass = Entity\StationMount::class; $this->entityClass = Entity\StationMount::class;
$this->form_configs = $form_configs; $this->form_configs = $form_configs;

View File

@ -5,6 +5,7 @@ use App\Customization;
use App\Entity; use App\Entity;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use App\Radio\PlaylistParser; use App\Radio\PlaylistParser;
use App\Settings;
use Azura\Config; use Azura\Config;
use AzuraForms\Field\Markup; use AzuraForms\Field\Markup;
use Cake\Chronos\Chronos; use Cake\Chronos\Chronos;
@ -17,7 +18,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
class StationPlaylistForm extends EntityForm class StationPlaylistForm extends EntityForm
{ {
/** @var Entity\Repository\StationPlaylistMediaRepository */ /** @var Entity\Repository\StationPlaylistMediaRepository */
protected $playlist_media_repo; protected $playlistMediaRepo;
/** /**
* @param EntityManager $em * @param EntityManager $em
@ -40,7 +41,7 @@ class StationPlaylistForm extends EntityForm
parent::__construct($em, $serializer, $validator, $form_config); parent::__construct($em, $serializer, $validator, $form_config);
$this->entityClass = Entity\StationPlaylist::class; $this->entityClass = Entity\StationPlaylist::class;
$this->playlist_media_repo = $em->getRepository(Entity\StationPlaylistMedia::class); $this->playlistMediaRepo = $em->getRepository(Entity\StationPlaylistMedia::class);
} }
public function process(ServerRequest $request, $record = null) public function process(ServerRequest $request, $record = null)
@ -147,13 +148,13 @@ class StationPlaylistForm extends EntityForm
->setParameter('matched_ids', $matches) ->setParameter('matched_ids', $matches)
->execute(); ->execute();
$weight = $this->playlist_media_repo->getHighestSongWeight($playlist); $weight = $this->playlistMediaRepo->getHighestSongWeight($playlist);
foreach ($matched_media as $media) { foreach ($matched_media as $media) {
$weight++; $weight++;
/** @var Entity\StationMedia $media */ /** @var Entity\StationMedia $media */
$this->playlist_media_repo->addMediaToPlaylist($media, $playlist, $weight); $this->playlistMediaRepo->addMediaToPlaylist($media, $playlist, $weight);
} }
$this->em->flush(); $this->em->flush();

View File

@ -5,7 +5,6 @@ use App\Entity;
use App\Http\Router; use App\Http\Router;
use App\Http\ServerRequest; use App\Http\ServerRequest;
use Azura\Config; use Azura\Config;
use Azura\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use InvalidArgumentException; use InvalidArgumentException;
use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Serializer;
@ -25,22 +24,19 @@ class StationWebhookForm extends EntityForm
* @param ValidatorInterface $validator * @param ValidatorInterface $validator
* @param Config $config * @param Config $config
* @param Router $router * @param Router $router
* @param Settings $settings
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Serializer $serializer, Serializer $serializer,
ValidatorInterface $validator, ValidatorInterface $validator,
Config $config, Config $config,
Router $router, Router $router
Settings $settings
) { ) {
$webhook_config = $config->get('webhooks'); $webhook_config = $config->get('webhooks');
$webhook_forms = []; $webhook_forms = [];
$config_injections = [ $config_injections = [
'router' => $router, 'router' => $router,
'app_settings' => $settings,
'triggers' => $webhook_config['triggers'], 'triggers' => $webhook_config['triggers'],
]; ];
foreach ($webhook_config['webhooks'] as $webhook_key => $webhook_info) { foreach ($webhook_config['webhooks'] as $webhook_key => $webhook_info) {

View File

@ -7,7 +7,7 @@ use App\Exception\PermissionDeniedException;
use App\Service\Sentry; use App\Service\Sentry;
use Azura\Exception; use Azura\Exception;
use Azura\Session; use Azura\Session;
use Azura\Settings; use App\Settings;
use Azura\View; use Azura\View;
use Gettext\Translator; use Gettext\Translator;
use Monolog\Logger; use Monolog\Logger;

View File

@ -2,7 +2,7 @@
namespace App\Http; namespace App\Http;
use App\Entity; use App\Entity;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;

View File

@ -4,7 +4,7 @@ namespace App\Notification;
use App\Acl; use App\Acl;
use App\Entity; use App\Entity;
use App\Event\GetNotifications; use App\Event\GetNotifications;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Monolog\Logger; use Monolog\Logger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;

View File

@ -5,10 +5,11 @@ use App\Entity;
use App\Exception\Supervisor\AlreadyRunningException; use App\Exception\Supervisor\AlreadyRunningException;
use App\Exception\Supervisor\BadNameException; use App\Exception\Supervisor\BadNameException;
use App\Exception\Supervisor\NotRunningException; use App\Exception\Supervisor\NotRunningException;
use App\Settings;
use Azura\EventDispatcher; use Azura\EventDispatcher;
use Azura\Logger;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use fXmlRpc\Exception\FaultException; use fXmlRpc\Exception\FaultException;
use Monolog\Logger;
use Supervisor\Process; use Supervisor\Process;
use Supervisor\Supervisor; use Supervisor\Supervisor;
@ -20,27 +21,21 @@ abstract class AbstractAdapter
/** @var Supervisor */ /** @var Supervisor */
protected $supervisor; protected $supervisor;
/** @var Logger */
protected $logger;
/** @var EventDispatcher */ /** @var EventDispatcher */
protected $dispatcher; protected $dispatcher;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Supervisor $supervisor * @param Supervisor $supervisor
* @param Logger $logger
* @param EventDispatcher $dispatcher * @param EventDispatcher $dispatcher
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Supervisor $supervisor, Supervisor $supervisor,
Logger $logger,
EventDispatcher $dispatcher EventDispatcher $dispatcher
) { ) {
$this->em = $em; $this->em = $em;
$this->supervisor = $supervisor; $this->supervisor = $supervisor;
$this->logger = $logger;
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
} }
@ -98,7 +93,7 @@ abstract class AbstractAdapter
*/ */
public function hasCommand(Entity\Station $station): bool public function hasCommand(Entity\Station $station): bool
{ {
if (APP_TESTING_MODE || !$station->isEnabled()) { if (Settings::getInstance()->isTesting() || !$station->isEnabled()) {
return false; return false;
} }
@ -152,7 +147,7 @@ abstract class AbstractAdapter
try { try {
$this->supervisor->stopProcess($program_name); $this->supervisor->stopProcess($program_name);
$this->logger->info('Adapter "' . get_called_class() . '" stopped.', Logger::getInstance()->info('Adapter "' . get_called_class() . '" stopped.',
['station_id' => $station->getId(), 'station_name' => $station->getName()]); ['station_id' => $station->getId(), 'station_name' => $station->getName()]);
} catch (FaultException $e) { } catch (FaultException $e) {
$this->_handleSupervisorException($e, $program_name, $station); $this->_handleSupervisorException($e, $program_name, $station);
@ -245,7 +240,7 @@ abstract class AbstractAdapter
try { try {
$this->supervisor->startProcess($program_name); $this->supervisor->startProcess($program_name);
$this->logger->info('Adapter "' . get_called_class() . '" started.', Logger::getInstance()->info('Adapter "' . get_called_class() . '" started.',
['station_id' => $station->getId(), 'station_name' => $station->getName()]); ['station_id' => $station->getId(), 'station_name' => $station->getName()]);
} catch (FaultException $e) { } catch (FaultException $e) {
$this->_handleSupervisorException($e, $program_name, $station); $this->_handleSupervisorException($e, $program_name, $station);
@ -268,15 +263,4 @@ abstract class AbstractAdapter
return $config_dir . '/' . strtolower($class_name) . '.log'; return $config_dir . '/' . strtolower($class_name) . '.log';
} }
/**
*
*
* @param array $clients
* @return array
*/
protected function _filterClients(array $clients): array
{
}
} }

View File

@ -7,10 +7,11 @@ use App\Event\Radio\WriteLiquidsoapConfiguration;
use App\Radio\Adapters; use App\Radio\Adapters;
use App\Radio\AutoDJ; use App\Radio\AutoDJ;
use App\Radio\Filesystem; use App\Radio\Filesystem;
use App\Settings;
use Azura\EventDispatcher; use Azura\EventDispatcher;
use Azura\Logger;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Exception; use Exception;
use Monolog\Logger;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
use Supervisor\Supervisor; use Supervisor\Supervisor;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@ -31,7 +32,6 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Supervisor $supervisor * @param Supervisor $supervisor
* @param Logger $logger
* @param EventDispatcher $dispatcher * @param EventDispatcher $dispatcher
* @param AutoDJ $autodj * @param AutoDJ $autodj
* @param Filesystem $filesystem * @param Filesystem $filesystem
@ -39,12 +39,11 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Supervisor $supervisor, Supervisor $supervisor,
Logger $logger,
EventDispatcher $dispatcher, EventDispatcher $dispatcher,
AutoDJ $autodj, AutoDJ $autodj,
Filesystem $filesystem Filesystem $filesystem
) { ) {
parent::__construct($em, $supervisor, $logger, $dispatcher); parent::__construct($em, $supervisor, $dispatcher);
$this->autodj = $autodj; $this->autodj = $autodj;
$this->filesystem = $filesystem; $this->filesystem = $filesystem;
@ -103,7 +102,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
'set("log.stdout", true)', 'set("log.stdout", true)',
'set("log.file", false)', 'set("log.file", false)',
'set("server.telnet",true)', 'set("server.telnet",true)',
'set("server.telnet.bind_addr","' . (APP_INSIDE_DOCKER ? '0.0.0.0' : '127.0.0.1') . '")', 'set("server.telnet.bind_addr","' . (Settings::getInstance()->isDocker() ? '0.0.0.0' : '127.0.0.1') . '")',
'set("server.telnet.port", ' . $this->_getTelnetPort($station) . ')', 'set("server.telnet.port", ' . $this->_getTelnetPort($station) . ')',
'set("harbor.bind_addrs",["0.0.0.0"])', 'set("harbor.bind_addrs",["0.0.0.0"])',
'', '',
@ -421,9 +420,9 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
]); ]);
} }
$error_file = APP_INSIDE_DOCKER $error_file = Settings::getInstance()->isDocker()
? '/usr/local/share/icecast/web/error.mp3' ? '/usr/local/share/icecast/web/error.mp3'
: APP_INCLUDE_ROOT . '/resources/error.mp3'; : Settings::getInstance()->getBaseDirectory() . '/resources/error.mp3';
$event->appendLines([ $event->appendLines([
'requests = audio_to_stereo(request.queue(id="' . $this->_getVarName('requests', $station) . '"))', 'requests = audio_to_stereo(request.queue(id="' . $this->_getVarName('requests', $station) . '"))',
@ -486,7 +485,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
try { try {
$this->command($station, $playlist_var_name . '.reload'); $this->command($station, $playlist_var_name . '.reload');
} catch (Exception $e) { } catch (Exception $e) {
$this->logger->error('Could not reload playlist with AutoDJ.', [ Logger::getInstance()->error('Could not reload playlist with AutoDJ.', [
'message' => $e->getMessage(), 'message' => $e->getMessage(),
'playlist' => $playlist_var_name, 'playlist' => $playlist_var_name,
'station' => $station->getId(), 'station' => $station->getId(),
@ -507,7 +506,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
*/ */
public function command(Entity\Station $station, $command_str) public function command(Entity\Station $station, $command_str)
{ {
$fp = stream_socket_client('tcp://' . (APP_INSIDE_DOCKER ? 'stations' : 'localhost') . ':' . $this->_getTelnetPort($station), $fp = stream_socket_client('tcp://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $this->_getTelnetPort($station),
$errno, $errstr, 20); $errno, $errstr, 20);
if (!$fp) { if (!$fp) {
@ -627,12 +626,14 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
*/ */
protected function _getApiUrlCommand(Entity\Station $station, $endpoint, $params = []): string protected function _getApiUrlCommand(Entity\Station $station, $endpoint, $params = []): string
{ {
$settings = Settings::getInstance();
// Docker cURL-based API URL call with API authentication. // Docker cURL-based API URL call with API authentication.
if (APP_INSIDE_DOCKER) { if ($settings->isDocker()) {
$params = (array)$params; $params = (array)$params;
$params['api_auth'] = '"' . $station->getAdapterApiKey() . '"'; $params['api_auth'] = '"' . $station->getAdapterApiKey() . '"';
$service_uri = (APP_DOCKER_REVISION >= 5) ? 'web' : 'nginx'; $service_uri = ($settings[Settings::DOCKER_REVISION] >= 5) ? 'web' : 'nginx';
$api_url = 'http://' . $service_uri . '/api/internal/' . $station->getId() . '/' . $endpoint; $api_url = 'http://' . $service_uri . '/api/internal/' . $station->getId() . '/' . $endpoint;
$command = 'curl -s --request POST --url ' . $api_url; $command = 'curl -s --request POST --url ' . $api_url;
foreach ($params as $param_key => $param_val) { foreach ($params as $param_key => $param_val) {
@ -640,7 +641,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
} }
} else { } else {
// Ansible shell-script call. // Ansible shell-script call.
$shell_path = '/usr/bin/php ' . APP_INCLUDE_ROOT . '/bin/azuracast'; $shell_path = '/usr/bin/php ' . $settings->getBaseDirectory() . '/bin/azuracast';
$shell_args = []; $shell_args = [];
$shell_args[] = 'azuracast:internal:' . $endpoint; $shell_args[] = 'azuracast:internal:' . $endpoint;
@ -962,7 +963,9 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
public static function getBinary() public static function getBinary()
{ {
// Docker revisions 3 and later use the `radio` container. // Docker revisions 3 and later use the `radio` container.
if (APP_INSIDE_DOCKER && APP_DOCKER_REVISION < 3) { $settings = Settings::getInstance();
if ($settings->isDocker() && $settings[Settings::DOCKER_REVISION] < 3) {
return '/var/azuracast/.opam/system/bin/liquidsoap'; return '/var/azuracast/.opam/system/bin/liquidsoap';
} }
@ -1053,7 +1056,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
$streamer = $streamer_repo->authenticate($station, $user, $pass); $streamer = $streamer_repo->authenticate($station, $user, $pass);
if ($streamer instanceof Entity\StationStreamer) { if ($streamer instanceof Entity\StationStreamer) {
$this->logger->debug('DJ successfully authenticated.', ['username' => $user]); Logger::getInstance()->debug('DJ successfully authenticated.', ['username' => $user]);
try { try {
// Successful authentication: update current streamer on station. // Successful authentication: update current streamer on station.
@ -1061,7 +1064,7 @@ class Liquidsoap extends AbstractBackend implements EventSubscriberInterface
$this->em->persist($station); $this->em->persist($station);
$this->em->flush(); $this->em->flush();
} catch (Exception $e) { } catch (Exception $e) {
$this->logger->error('Error when calling post-DJ-authentication functions.', [ Logger::getInstance()->error('Error when calling post-DJ-authentication functions.', [
'file' => $e->getFile(), 'file' => $e->getFile(),
'line' => $e->getLine(), 'line' => $e->getLine(),
'code' => $e->getCode(), 'code' => $e->getCode(),

View File

@ -2,6 +2,7 @@
namespace App\Radio; namespace App\Radio;
use App\Entity\Station; use App\Entity\Station;
use App\Settings;
use Azura\Exception; use Azura\Exception;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use fXmlRpc\Exception\FaultException; use fXmlRpc\Exception\FaultException;
@ -55,7 +56,7 @@ class Configuration
*/ */
public function writeConfiguration(Station $station, $regen_auth_key = false, $force_restart = false): void public function writeConfiguration(Station $station, $regen_auth_key = false, $force_restart = false): void
{ {
if (APP_TESTING_MODE) { if (Settings::getInstance()->isTesting()) {
return; return;
} }
@ -408,7 +409,7 @@ class Configuration
*/ */
public function removeConfiguration(Station $station): void public function removeConfiguration(Station $station): void
{ {
if (APP_TESTING_MODE) { if (Settings::getInstance()->isTesting()) {
return; return;
} }

View File

@ -4,12 +4,13 @@ namespace App\Radio\Frontend;
use App\Entity; use App\Entity;
use App\Http\Router; use App\Http\Router;
use App\Radio\AbstractAdapter; use App\Radio\AbstractAdapter;
use App\Settings;
use App\Xml\Reader; use App\Xml\Reader;
use Azura\EventDispatcher; use Azura\EventDispatcher;
use Azura\Logger;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use Monolog\Logger;
use NowPlaying\Adapter\AdapterAbstract; use NowPlaying\Adapter\AdapterAbstract;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
use Supervisor\Supervisor; use Supervisor\Supervisor;
@ -25,12 +26,11 @@ abstract class AbstractFrontend extends AbstractAdapter
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Supervisor $supervisor, Supervisor $supervisor,
Logger $logger,
EventDispatcher $dispatcher, EventDispatcher $dispatcher,
Client $client, Client $client,
Router $router Router $router
) { ) {
parent::__construct($em, $supervisor, $logger, $dispatcher); parent::__construct($em, $supervisor, $dispatcher);
$this->http_client = $client; $this->http_client = $client;
$this->router = $router; $this->router = $router;
@ -146,7 +146,7 @@ abstract class AbstractFrontend extends AbstractAdapter
$use_radio_proxy = $settings_repo->getSetting('use_radio_proxy', 0); $use_radio_proxy = $settings_repo->getSetting('use_radio_proxy', 0);
if ($use_radio_proxy if ($use_radio_proxy
|| (!APP_IN_PRODUCTION && !APP_INSIDE_DOCKER) || (!Settings::getInstance()->isProduction() && !Settings::getInstance()->isDocker())
|| 'https' === $base_url->getScheme()) { || 'https' === $base_url->getScheme()) {
// Web proxy support. // Web proxy support.
return $base_url return $base_url
@ -223,7 +223,7 @@ abstract class AbstractFrontend extends AbstractAdapter
$np['listeners']['clients'] = []; $np['listeners']['clients'] = [];
} }
$this->logger->debug('Response for mount point', ['mount' => $mount->getName(), 'response' => $np]); Logger::getInstance()->debug('Response for mount point', ['mount' => $mount->getName(), 'response' => $np]);
$mount->setListenersTotal($np['listeners']['total']); $mount->setListenersTotal($np['listeners']['total']);
$mount->setListenersUnique($np['listeners']['unique']); $mount->setListenersUnique($np['listeners']['unique']);

View File

@ -2,9 +2,11 @@
namespace App\Radio\Frontend; namespace App\Radio\Frontend;
use App\Entity; use App\Entity;
use App\Settings;
use App\Utilities; use App\Utilities;
use App\Xml\Reader; use App\Xml\Reader;
use App\Xml\Writer; use App\Xml\Writer;
use Azura\Logger;
use NowPlaying\Adapter\AdapterAbstract; use NowPlaying\Adapter\AdapterAbstract;
use NowPlaying\Exception; use NowPlaying\Exception;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
@ -21,7 +23,7 @@ class Icecast extends AbstractFrontend
$fe_config = (array)$station->getFrontendConfig(); $fe_config = (array)$station->getFrontendConfig();
$radio_port = $fe_config['port']; $radio_port = $fe_config['port'];
$base_url = 'http://' . (APP_INSIDE_DOCKER ? 'stations' : 'localhost') . ':' . $radio_port; $base_url = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radio_port;
$np_adapter = new \NowPlaying\Adapter\Icecast($base_url, $this->http_client); $np_adapter = new \NowPlaying\Adapter\Icecast($base_url, $this->http_client);
$np_adapter->setAdminPassword($fe_config['admin_pw']); $np_adapter->setAdminPassword($fe_config['admin_pw']);
@ -40,9 +42,9 @@ class Icecast extends AbstractFrontend
); );
} }
$this->logger->debug('Aggregated NowPlaying response', ['response' => $np_final]); Logger::getInstance()->debug('Aggregated NowPlaying response', ['response' => $np_final]);
} catch (Exception $e) { } catch (Exception $e) {
$this->logger->error(sprintf('NowPlaying adapter error: %s', $e->getMessage())); Logger::getInstance()->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
} }
return $np_final; return $np_final;
@ -129,7 +131,7 @@ class Icecast extends AbstractFrontend
'logging' => [ 'logging' => [
'accesslog' => 'icecast_access.log', 'accesslog' => 'icecast_access.log',
'errorlog' => '/dev/stderr', 'errorlog' => '/dev/stderr',
'loglevel' => (APP_IN_PRODUCTION) ? self::LOGLEVEL_WARN : self::LOGLEVEL_INFO, 'loglevel' => Settings::getInstance()->isProduction() ? self::LOGLEVEL_WARN : self::LOGLEVEL_INFO,
'logsize' => 10000, 'logsize' => 10000,
], ],
'security' => [ 'security' => [
@ -138,7 +140,9 @@ class Icecast extends AbstractFrontend
]; ];
// Allow all sources to set the X-Forwarded-For header // Allow all sources to set the X-Forwarded-For header
if (APP_INSIDE_DOCKER && APP_DOCKER_REVISION >= 3) { $settings = Settings::getInstance();
if ($settings->isDocker() && $settings[Settings::DOCKER_REVISION] >= 3) {
$defaults['paths']['all-x-forwarded-for'] = '1'; $defaults['paths']['all-x-forwarded-for'] = '1';
} }
@ -318,7 +322,7 @@ class Icecast extends AbstractFrontend
$new_path = '/usr/local/bin/icecast'; $new_path = '/usr/local/bin/icecast';
$legacy_path = '/usr/bin/icecast2'; $legacy_path = '/usr/bin/icecast2';
if (APP_INSIDE_DOCKER || file_exists($new_path)) { if (Settings::getInstance()->isDocker() || file_exists($new_path)) {
return $new_path; return $new_path;
} elseif (file_exists($legacy_path)) { } elseif (file_exists($legacy_path)) {
return $legacy_path; return $legacy_path;

View File

@ -2,6 +2,7 @@
namespace App\Radio\Frontend; namespace App\Radio\Frontend;
use App\Entity; use App\Entity;
use App\Settings;
use App\Utilities; use App\Utilities;
use NowPlaying\Adapter\AdapterAbstract; use NowPlaying\Adapter\AdapterAbstract;
use NowPlaying\Adapter\SHOUTcast2; use NowPlaying\Adapter\SHOUTcast2;
@ -34,10 +35,11 @@ class SHOUTcast extends AbstractFrontend
public static function getBinary() public static function getBinary()
{ {
$new_path = dirname(APP_INCLUDE_ROOT) . '/servers/shoutcast2/sc_serv'; $new_path = '/var/azuracast/servers/shoutcast2/sc_serv';
// Docker versions before 3 included the SC binary across the board. // Docker versions before 3 included the SC binary across the board.
if (APP_INSIDE_DOCKER && APP_DOCKER_REVISION < 3) { $settings = Settings::getInstance();
if ($settings->isDocker() && $settings[Settings::DOCKER_REVISION] < 3) {
return $new_path; return $new_path;
} }
@ -51,7 +53,7 @@ class SHOUTcast extends AbstractFrontend
$fe_config = (array)$station->getFrontendConfig(); $fe_config = (array)$station->getFrontendConfig();
$radio_port = $fe_config['port']; $radio_port = $fe_config['port'];
$base_url = 'http://' . (APP_INSIDE_DOCKER ? 'stations' : 'localhost') . ':' . $radio_port; $base_url = 'http://' . (Settings::getInstance()->isDocker() ? 'stations' : 'localhost') . ':' . $radio_port;
$np_adapter = new SHOUTcast2($base_url, $this->http_client); $np_adapter = new SHOUTcast2($base_url, $this->http_client);
$np_adapter->setAdminPassword($fe_config['admin_pw']); $np_adapter->setAdminPassword($fe_config['admin_pw']);

View File

@ -2,6 +2,7 @@
namespace App\Radio\Remote; namespace App\Radio\Remote;
use App\Entity; use App\Entity;
use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;

View File

@ -2,6 +2,7 @@
namespace App\Radio\Remote; namespace App\Radio\Remote;
use App\Entity; use App\Entity;
use App\Settings;
use GuzzleHttp\Psr7\Uri; use GuzzleHttp\Psr7\Uri;
use InvalidArgumentException; use InvalidArgumentException;
@ -59,7 +60,7 @@ class AzuraRelay extends AbstractRemote
$use_radio_proxy = $settings_repo->getSetting('use_radio_proxy', 0); $use_radio_proxy = $settings_repo->getSetting('use_radio_proxy', 0);
if ($use_radio_proxy if ($use_radio_proxy
|| (!APP_IN_PRODUCTION && !APP_INSIDE_DOCKER) || (!Settings::getInstance()->isProduction() && !Settings::getInstance()->isDocker())
|| 'https' === $base_url->getScheme()) { || 'https' === $base_url->getScheme()) {
// Web proxy support. // Web proxy support.
return (string)$base_url return (string)$base_url

View File

@ -3,7 +3,7 @@ namespace App\Service;
use App\Entity; use App\Entity;
use App\Version; use App\Version;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Client; use GuzzleHttp\Client;

View File

@ -5,7 +5,7 @@ use App\Acl;
use App\Entity; use App\Entity;
use App\Http\Router; use App\Http\Router;
use App\Utilities; use App\Utilities;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use RuntimeException; use RuntimeException;

View File

@ -1,6 +1,8 @@
<?php <?php
namespace App\Service; namespace App\Service;
use App\Settings;
/** /**
* Utility class for managing NChan, the nginx websocket/SSE/long-polling module. * Utility class for managing NChan, the nginx websocket/SSE/long-polling module.
*/ */
@ -11,12 +13,14 @@ class NChan
*/ */
public static function isSupported(): bool public static function isSupported(): bool
{ {
if (APP_TESTING_MODE) { $settings = Settings::getInstance();
if ($settings->isTesting()) {
return false; return false;
} }
if (APP_INSIDE_DOCKER) { if ($settings->isDocker()) {
return APP_DOCKER_REVISION >= 5; return $settings[Settings::DOCKER_REVISION] >= 5;
} }
$os_details = self::getOperatingSystemDetails(); $os_details = self::getOperatingSystemDetails();

View File

@ -5,7 +5,7 @@ use App\Entity;
use App\Exception\SupervisorException; use App\Exception\SupervisorException;
use App\Version; use App\Version;
use Azura\Exception; use Azura\Exception;
use Azura\Settings; use App\Settings;
use Doctrine\DBAL\Exception\TableNotFoundException; use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use fXmlRpc\Exception\FaultException; use fXmlRpc\Exception\FaultException;
@ -72,7 +72,7 @@ class Sentry
return; return;
} }
if (APP_TESTING_MODE) { if ($this->app_settings->isTesting()) {
return; return;
} }

25
src/Settings.php Normal file
View File

@ -0,0 +1,25 @@
<?php
namespace App;
class Settings extends \Azura\Settings
{
public const DOCKER_REVISION = 'docker_revision';
/**
* @return string The parent directory the application is within, i.e. `/var/azuracast`.
*/
public function getParentDirectory(): string
{
return dirname($this->getBaseDirectory());
}
/**
* @return string The default directory where station data is stored.
*/
public function getStationDirectory(): string
{
return $this->getParentDirectory().'/stations';
}
}

View File

@ -3,6 +3,7 @@ namespace App\Sync;
use App\Entity; use App\Entity;
use App\Entity\Repository\SettingsRepository; use App\Entity\Repository\SettingsRepository;
use App\Settings;
use Monolog\Logger; use Monolog\Logger;
use Pimple\ServiceIterator; use Pimple\ServiceIterator;
@ -15,7 +16,7 @@ class Runner
protected $logger; protected $logger;
/** @var SettingsRepository */ /** @var SettingsRepository */
protected $settings; protected $settingsRepo;
/** @var Task\AbstractTask[] */ /** @var Task\AbstractTask[] */
protected $tasks_nowplaying; protected $tasks_nowplaying;
@ -30,14 +31,14 @@ class Runner
protected $tasks_long; protected $tasks_long;
public function __construct( public function __construct(
SettingsRepository $settings, SettingsRepository $settingsRepo,
Logger $logger, Logger $logger,
array $tasks_nowplaying, array $tasks_nowplaying,
array $tasks_short, array $tasks_short,
array $tasks_medium, array $tasks_medium,
array $tasks_long array $tasks_long
) { ) {
$this->settings = $settings; $this->settingsRepo = $settingsRepo;
$this->logger = $logger; $this->logger = $logger;
$this->tasks_nowplaying = $tasks_nowplaying; $this->tasks_nowplaying = $tasks_nowplaying;
@ -59,14 +60,14 @@ class Runner
$this->_initSync(10); $this->_initSync(10);
// Prevent nowplaying from running on top of itself. // Prevent nowplaying from running on top of itself.
$last_start = $this->settings->getSetting(Entity\Settings::NOWPLAYING_LAST_STARTED, 0); $last_start = $this->settingsRepo->getSetting(Entity\Settings::NOWPLAYING_LAST_STARTED, 0);
$last_end = $this->settings->getSetting(Entity\Settings::NOWPLAYING_LAST_RUN, 0); $last_end = $this->settingsRepo->getSetting(Entity\Settings::NOWPLAYING_LAST_RUN, 0);
if ($last_start > $last_end && $last_start >= (time() - 10) && !$force) { if ($last_start > $last_end && $last_start >= (time() - 10) && !$force) {
return; return;
} }
$this->settings->setSetting(Entity\Settings::NOWPLAYING_LAST_STARTED, time()); $this->settingsRepo->setSetting(Entity\Settings::NOWPLAYING_LAST_STARTED, time());
foreach ($this->tasks_nowplaying as $task) { foreach ($this->tasks_nowplaying as $task) {
$this->_runTimer(get_class($task), function () use ($task, $force) { $this->_runTimer(get_class($task), function () use ($task, $force) {
@ -75,20 +76,20 @@ class Runner
}); });
} }
$this->settings->setSetting(Entity\Settings::NOWPLAYING_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::NOWPLAYING_LAST_RUN, time());
} }
protected function _initSync($script_timeout = 60) protected function _initSync($script_timeout = 60)
{ {
// Immediately halt if setup is not complete. // Immediately halt if setup is not complete.
if ($this->settings->getSetting(Entity\Settings::SETUP_COMPLETE, 0) == 0) { if ($this->settingsRepo->getSetting(Entity\Settings::SETUP_COMPLETE, 0) == 0) {
die('Setup not complete; halting synchronized task.'); die('Setup not complete; halting synchronized task.');
} }
set_time_limit($script_timeout); set_time_limit($script_timeout);
ini_set('memory_limit', '256M'); ini_set('memory_limit', '256M');
if (APP_IS_COMMAND_LINE) { if (Settings::getInstance()->isCli()) {
error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE); error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE);
ini_set('display_errors', 1); ini_set('display_errors', 1);
ini_set('log_errors', 1); ini_set('log_errors', 1);
@ -129,7 +130,7 @@ class Runner
}); });
} }
$this->settings->setSetting(Entity\Settings::SHORT_SYNC_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::SHORT_SYNC_LAST_RUN, time());
} }
/** /**
@ -150,7 +151,7 @@ class Runner
}); });
} }
$this->settings->setSetting(Entity\Settings::MEDIUM_SYNC_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::MEDIUM_SYNC_LAST_RUN, time());
} }
/** /**
@ -171,38 +172,38 @@ class Runner
}); });
} }
$this->settings->setSetting(Entity\Settings::LONG_SYNC_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::LONG_SYNC_LAST_RUN, time());
} }
public function getSyncTimes() public function getSyncTimes()
{ {
$this->settings->clearCache(); $this->settingsRepo->clearCache();
$syncs = [ $syncs = [
'nowplaying' => [ 'nowplaying' => [
'name' => __('Now Playing Data'), 'name' => __('Now Playing Data'),
'latest' => $this->settings->getSetting(Entity\Settings::NOWPLAYING_LAST_RUN, 0), 'latest' => $this->settingsRepo->getSetting(Entity\Settings::NOWPLAYING_LAST_RUN, 0),
'contents' => [ 'contents' => [
__('Now Playing Data'), __('Now Playing Data'),
], ],
], ],
'short' => [ 'short' => [
'name' => __('1-Minute Sync'), 'name' => __('1-Minute Sync'),
'latest' => $this->settings->getSetting(Entity\Settings::SHORT_SYNC_LAST_RUN, 0), 'latest' => $this->settingsRepo->getSetting(Entity\Settings::SHORT_SYNC_LAST_RUN, 0),
'contents' => [ 'contents' => [
__('Song Requests Queue'), __('Song Requests Queue'),
], ],
], ],
'medium' => [ 'medium' => [
'name' => __('5-Minute Sync'), 'name' => __('5-Minute Sync'),
'latest' => $this->settings->getSetting(Entity\Settings::MEDIUM_SYNC_LAST_RUN, 0), 'latest' => $this->settingsRepo->getSetting(Entity\Settings::MEDIUM_SYNC_LAST_RUN, 0),
'contents' => [ 'contents' => [
__('Check Media Folders'), __('Check Media Folders'),
], ],
], ],
'long' => [ 'long' => [
'name' => __('1-Hour Sync'), 'name' => __('1-Hour Sync'),
'latest' => $this->settings->getSetting(Entity\Settings::LONG_SYNC_LAST_RUN, 0), 'latest' => $this->settingsRepo->getSetting(Entity\Settings::LONG_SYNC_LAST_RUN, 0),
'contents' => [ 'contents' => [
__('Analytics/Statistics'), __('Analytics/Statistics'),
__('Cleanup'), __('Cleanup'),

View File

@ -1,26 +1,24 @@
<?php <?php
namespace App\Sync\Task; namespace App\Sync\Task;
use App\Entity;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Interop\Container\ContainerInterface;
use Monolog\Logger;
abstract class AbstractTask abstract class AbstractTask
{ {
/** @var EntityManager */ /** @var EntityManager */
protected $em; protected $em;
/** @var Logger */ /** @var Entity\Repository\SettingsRepository */
protected $logger; protected $settingsRepo;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
*/ */
public function __construct(EntityManager $em, Logger $logger) public function __construct(EntityManager $em)
{ {
$this->em = $em; $this->em = $em;
$this->logger = $logger; $this->settingsRepo = $em->getRepository(Entity\Settings::class);
} }
abstract public function run($force = false): void; abstract public function run($force = false): void;

View File

@ -2,6 +2,7 @@
namespace App\Sync\Task; namespace App\Sync\Task;
use App\Entity; use App\Entity;
use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use InfluxDB\Database; use InfluxDB\Database;
use Monolog\Logger; use Monolog\Logger;
@ -13,22 +14,18 @@ class Analytics extends AbstractTask
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Database $influx * @param Database $influx
*/ */
public function __construct(EntityManager $em, Logger $logger, Database $influx) public function __construct(EntityManager $em, Database $influx)
{ {
parent::__construct($em, $logger); parent::__construct($em);
$this->influx = $influx; $this->influx = $influx;
} }
public function run($force = false): void public function run($force = false): void
{ {
/** @var Entity\Repository\SettingsRepository $settings_repo */ $analytics_level = $this->settingsRepo->getSetting('analytics', Entity\Analytics::LEVEL_ALL);
$settings_repo = $this->em->getRepository(Entity\Settings::class);
$analytics_level = $settings_repo->getSetting('analytics', Entity\Analytics::LEVEL_ALL);
if ($analytics_level === Entity\Analytics::LEVEL_NONE) { if ($analytics_level === Entity\Analytics::LEVEL_NONE) {
$this->_purgeAnalytics(); $this->_purgeAnalytics();

View File

@ -4,6 +4,7 @@ namespace App\Sync\Task;
use App\Entity; use App\Entity;
use App\Message; use App\Message;
use App\MessageQueue; use App\MessageQueue;
use App\Settings;
use Azura\Console\Application; use Azura\Console\Application;
use Cake\Chronos\Chronos; use Cake\Chronos\Chronos;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
@ -13,32 +14,25 @@ class Backup extends AbstractTask
{ {
public const BASE_DIR = '/var/azuracast/backups'; public const BASE_DIR = '/var/azuracast/backups';
/** @var Entity\Repository\SettingsRepository */
protected $settings_repo;
/** @var MessageQueue */ /** @var MessageQueue */
protected $message_queue; protected $messageQueue;
/** @var Application */ /** @var Application */
protected $console; protected $console;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param MessageQueue $message_queue * @param MessageQueue $message_queue
* @param Application $console * @param Application $console
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger,
MessageQueue $message_queue, MessageQueue $message_queue,
Application $console Application $console
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->settings_repo = $em->getRepository(Entity\Settings::class); $this->messageQueue = $message_queue;
$this->message_queue = $message_queue;
$this->console = $console; $this->console = $console;
} }
@ -56,9 +50,9 @@ class Backup extends AbstractTask
$message->exclude_media $message->exclude_media
); );
$this->settings_repo->setSetting(Entity\Settings::BACKUP_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::BACKUP_LAST_RUN, time());
$this->settings_repo->setSetting(Entity\Settings::BACKUP_LAST_RESULT, $result_code); $this->settingsRepo->setSetting(Entity\Settings::BACKUP_LAST_RESULT, $result_code);
$this->settings_repo->setSetting(Entity\Settings::BACKUP_LAST_OUTPUT, $result_output); $this->settingsRepo->setSetting(Entity\Settings::BACKUP_LAST_OUTPUT, $result_output);
} }
} }
@ -77,7 +71,7 @@ class Backup extends AbstractTask
$input_params['--exclude-media'] = true; $input_params['--exclude-media'] = true;
} }
return $this->console->runCommand('azuracast:backup', $input_params); return $this->console->runCommandWithArgs('azuracast:backup', $input_params);
} }
/** /**
@ -85,20 +79,20 @@ class Backup extends AbstractTask
*/ */
public function run($force = false): void public function run($force = false): void
{ {
$backup_enabled = (bool)$this->settings_repo->getSetting(Entity\Settings::BACKUP_ENABLED, 0); $backup_enabled = (bool)$this->settingsRepo->getSetting(Entity\Settings::BACKUP_ENABLED, 0);
if (!$backup_enabled) { if (!$backup_enabled) {
$this->logger->debug('Automated backups disabled; skipping...'); \Azura\Logger::getInstance()->debug('Automated backups disabled; skipping...');
return; return;
} }
$now_utc = Chronos::now('UTC'); $now_utc = Chronos::now('UTC');
$threshold = $now_utc->subDay()->getTimestamp(); $threshold = $now_utc->subDay()->getTimestamp();
$last_run = $this->settings_repo->getSetting(Entity\Settings::BACKUP_LAST_RUN, 0); $last_run = $this->settingsRepo->getSetting(Entity\Settings::BACKUP_LAST_RUN, 0);
if ($last_run <= $threshold) { if ($last_run <= $threshold) {
// Check if the backup time matches (if it's set). // Check if the backup time matches (if it's set).
$backup_timecode = (int)$this->settings_repo->getSetting(Entity\Settings::BACKUP_TIME); $backup_timecode = (int)$this->settingsRepo->getSetting(Entity\Settings::BACKUP_TIME);
if (0 !== $backup_timecode) { if (0 !== $backup_timecode) {
$current_timecode = (int)$now_utc->format('Hi'); $current_timecode = (int)$now_utc->format('Hi');
@ -110,8 +104,8 @@ class Backup extends AbstractTask
// Trigger a new backup. // Trigger a new backup.
$message = new Message\BackupMessage; $message = new Message\BackupMessage;
$message->path = 'automatic_backup.zip'; $message->path = 'automatic_backup.zip';
$message->exclude_media = (bool)$this->settings_repo->getSetting(Entity\Settings::BACKUP_EXCLUDE_MEDIA, 0); $message->exclude_media = (bool)$this->settingsRepo->getSetting(Entity\Settings::BACKUP_EXCLUDE_MEDIA, 0);
$this->message_queue->produce($message); $this->messageQueue->produce($message);
} }
} }
} }

View File

@ -3,7 +3,7 @@ namespace App\Sync\Task;
use App\Entity; use App\Entity;
use App\Service\AzuraCastCentral; use App\Service\AzuraCastCentral;
use Azura\Settings; use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Exception\TransferException; use GuzzleHttp\Exception\TransferException;
use Monolog\Logger; use Monolog\Logger;
@ -12,68 +12,57 @@ class CheckForUpdates extends AbstractTask
{ {
protected const UPDATE_THRESHOLD = 3780; protected const UPDATE_THRESHOLD = 3780;
/** @var Entity\Repository\SettingsRepository */
protected $settings_repo;
/** @var Settings */
protected $app_settings;
/** @var AzuraCastCentral */ /** @var AzuraCastCentral */
protected $azuracast_central; protected $azuracastCentral;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger * @param AzuraCastCentral $azuracastCentral
* @param Settings $app_settings
* @param AzuraCastCentral $azuracast_central
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger, AzuraCastCentral $azuracastCentral
Settings $app_settings,
AzuraCastCentral $azuracast_central
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->settings_repo = $em->getRepository(Entity\Settings::class); $this->azuracastCentral = $azuracastCentral;
$this->app_settings = $app_settings;
$this->azuracast_central = $azuracast_central;
} }
public function run($force = false): void public function run($force = false): void
{ {
$logger = \Azura\Logger::getInstance();
if (!$force) { if (!$force) {
$update_last_run = (int)$this->settings_repo->getSetting(Entity\Settings::UPDATE_LAST_RUN, 0); $update_last_run = (int)$this->settingsRepo->getSetting(Entity\Settings::UPDATE_LAST_RUN, 0);
if ($update_last_run > (time() - self::UPDATE_THRESHOLD)) { if ($update_last_run > (time() - self::UPDATE_THRESHOLD)) {
$this->logger->debug('Not checking for updates; checked too recently.'); $logger->debug('Not checking for updates; checked too recently.');
return; return;
} }
} }
$check_for_updates = (int)$this->settings_repo->getSetting(Entity\Settings::CENTRAL_UPDATES, $check_for_updates = (int)$this->settingsRepo->getSetting(Entity\Settings::CENTRAL_UPDATES,
Entity\Settings::UPDATES_RELEASE_ONLY); Entity\Settings::UPDATES_RELEASE_ONLY);
if (Entity\Settings::UPDATES_NONE === $check_for_updates || $this->app_settings->isTesting()) { if (Entity\Settings::UPDATES_NONE === $check_for_updates || Settings::getInstance()->isTesting()) {
$this->logger->info('Update checks are currently disabled for this AzuraCast instance.'); $logger->info('Update checks are currently disabled for this AzuraCast instance.');
return; return;
} }
try { try {
$updates = $this->azuracast_central->checkForUpdates(); $updates = $this->azuracastCentral->checkForUpdates();
if (!empty($updates)) { if (!empty($updates)) {
$this->settings_repo->setSetting(Entity\Settings::UPDATE_RESULTS, $updates); $this->settingsRepo->setSetting(Entity\Settings::UPDATE_RESULTS, $updates);
$this->logger->info('Successfully checked for updates.', ['results' => $updates]); $logger->info('Successfully checked for updates.', ['results' => $updates]);
} else { } else {
$this->logger->error('Error parsing update data response from AzuraCast central.'); $logger->error('Error parsing update data response from AzuraCast central.');
} }
} catch (TransferException $e) { } catch (TransferException $e) {
$this->logger->error(sprintf('Error from AzuraCast Central (%d): %s', $e->getCode(), $e->getMessage())); $logger->error(sprintf('Error from AzuraCast Central (%d): %s', $e->getCode(), $e->getMessage()));
return; return;
} }
$this->settings_repo->setSetting(Entity\Settings::UPDATE_LAST_RUN, time()); $this->settingsRepo->setSetting(Entity\Settings::UPDATE_LAST_RUN, time());
} }
} }

View File

@ -6,6 +6,7 @@ use App\Message;
use App\MessageQueue; use App\MessageQueue;
use App\Radio\Filesystem; use App\Radio\Filesystem;
use App\Radio\Quota; use App\Radio\Quota;
use App\Settings;
use Bernard\Envelope; use Bernard\Envelope;
use Brick\Math\BigInteger; use Brick\Math\BigInteger;
use Doctrine\Common\Persistence\Mapping\MappingException; use Doctrine\Common\Persistence\Mapping\MappingException;
@ -19,24 +20,22 @@ class Media extends AbstractTask
protected $filesystem; protected $filesystem;
/** @var MessageQueue */ /** @var MessageQueue */
protected $message_queue; protected $messageQueue;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Filesystem $filesystem * @param Filesystem $filesystem
* @param MessageQueue $message_queue * @param MessageQueue $messageQueue
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger,
Filesystem $filesystem, Filesystem $filesystem,
MessageQueue $message_queue MessageQueue $messageQueue
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->filesystem = $filesystem; $this->filesystem = $filesystem;
$this->message_queue = $message_queue; $this->messageQueue = $messageQueue;
} }
/** /**
@ -128,7 +127,7 @@ class Media extends AbstractTask
$queued_media_updates = []; $queued_media_updates = [];
$queued_new_files = []; $queued_new_files = [];
$queue = $this->message_queue->getGlobalQueue(); $queue = $this->messageQueue->getGlobalQueue();
$queue_position = 0; $queue_position = 0;
$queue_iteration = 20; $queue_iteration = 20;
@ -195,7 +194,7 @@ class Media extends AbstractTask
$message->media_id = $media_row->getId(); $message->media_id = $media_row->getId();
$message->force = $force_reprocess; $message->force = $force_reprocess;
$this->message_queue->produce($message); $this->messageQueue->produce($message);
$stats['updated']++; $stats['updated']++;
} else { } else {
@ -232,7 +231,7 @@ class Media extends AbstractTask
$message->station_id = $station->getId(); $message->station_id = $station->getId();
$message->path = $new_music_file['path']; $message->path = $new_music_file['path'];
$this->message_queue->produce($message); $this->messageQueue->produce($message);
$stats['created']++; $stats['created']++;
} }
@ -240,7 +239,7 @@ class Media extends AbstractTask
$fs->flushAllCaches(true); $fs->flushAllCaches(true);
$this->logger->debug(sprintf('Media processed for station "%s".', $station->getName()), $stats); \Azura\Logger::getInstance()->debug(sprintf('Media processed for station "%s".', $station->getName()), $stats);
} }
/** /**

View File

@ -9,6 +9,7 @@ use App\Message;
use App\MessageQueue; use App\MessageQueue;
use App\Radio\Adapters; use App\Radio\Adapters;
use App\Radio\AutoDJ; use App\Radio\AutoDJ;
use App\Settings;
use Azura\EventDispatcher; use Azura\EventDispatcher;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Exception; use Exception;
@ -41,6 +42,9 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
/** @var MessageQueue */ /** @var MessageQueue */
protected $message_queue; protected $message_queue;
/** @var Logger */
protected $logger;
/** @var ApiUtilities */ /** @var ApiUtilities */
protected $api_utils; protected $api_utils;
@ -61,27 +65,27 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Adapters $adapters * @param Adapters $adapters
* @param ApiUtilities $api_utils * @param ApiUtilities $api_utils
* @param AutoDJ $autodj * @param AutoDJ $autodj
* @param CacheInterface $cache * @param CacheInterface $cache
* @param Database $influx * @param Database $influx
* @param Logger $logger
* @param EventDispatcher $event_dispatcher * @param EventDispatcher $event_dispatcher
* @param MessageQueue $message_queue * @param MessageQueue $message_queue
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger,
Adapters $adapters, Adapters $adapters,
ApiUtilities $api_utils, ApiUtilities $api_utils,
AutoDJ $autodj, AutoDJ $autodj,
CacheInterface $cache, CacheInterface $cache,
Database $influx, Database $influx,
Logger $logger,
EventDispatcher $event_dispatcher, EventDispatcher $event_dispatcher,
MessageQueue $message_queue MessageQueue $message_queue
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->adapters = $adapters; $this->adapters = $adapters;
$this->api_utils = $api_utils; $this->api_utils = $api_utils;
@ -90,6 +94,7 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
$this->event_dispatcher = $event_dispatcher; $this->event_dispatcher = $event_dispatcher;
$this->message_queue = $message_queue; $this->message_queue = $message_queue;
$this->influx = $influx; $this->influx = $influx;
$this->logger = $logger;
$this->history_repo = $em->getRepository(Entity\SongHistory::class); $this->history_repo = $em->getRepository(Entity\SongHistory::class);
$this->song_repo = $em->getRepository(Entity\Song::class); $this->song_repo = $em->getRepository(Entity\Song::class);
@ -104,7 +109,7 @@ class NowPlaying extends AbstractTask implements EventSubscriberInterface
public static function getSubscribedEvents() public static function getSubscribedEvents()
{ {
if (APP_TESTING_MODE) { if (Settings::getInstance()->isTesting()) {
return []; return [];
} }

View File

@ -17,12 +17,11 @@ class RadioAutomation extends AbstractTask
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Adapters $adapters * @param Adapters $adapters
*/ */
public function __construct(EntityManager $em, Logger $logger, Adapters $adapters) public function __construct(EntityManager $em, Adapters $adapters)
{ {
parent::__construct($em, $logger); parent::__construct($em);
$this->adapters = $adapters; $this->adapters = $adapters;
} }

View File

@ -5,8 +5,8 @@ use App\Entity;
use App\Event\Radio\AnnotateNextSong; use App\Event\Radio\AnnotateNextSong;
use App\Radio\Adapters; use App\Radio\Adapters;
use Azura\EventDispatcher; use Azura\EventDispatcher;
use Azura\Logger;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Monolog\Logger;
class RadioRequests extends AbstractTask class RadioRequests extends AbstractTask
{ {
@ -18,17 +18,15 @@ class RadioRequests extends AbstractTask
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Adapters $adapters * @param Adapters $adapters
* @param EventDispatcher $dispatcher * @param EventDispatcher $dispatcher
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger,
Adapters $adapters, Adapters $adapters,
EventDispatcher $dispatcher EventDispatcher $dispatcher
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->dispatcher = $dispatcher; $this->dispatcher = $dispatcher;
$this->adapters = $adapters; $this->adapters = $adapters;
@ -117,10 +115,10 @@ class RadioRequests extends AbstractTask
$track = $event->buildAnnotations(); $track = $event->buildAnnotations();
// Queue request with Liquidsoap. // Queue request with Liquidsoap.
$this->logger->debug('Submitting request to AutoDJ.', ['track' => $track]); Logger::getInstance()->debug('Submitting request to AutoDJ.', ['track' => $track]);
$response = $backend->request($station, $track); $response = $backend->request($station, $track);
$this->logger->debug('AutoDJ request response', ['response' => $response]); Logger::getInstance()->debug('AutoDJ request response', ['response' => $response]);
// Log the request as played. // Log the request as played.
$request->setPlayedAt(time()); $request->setPlayedAt(time());

View File

@ -3,8 +3,9 @@ namespace App\Sync\Task;
use App\Entity; use App\Entity;
use App\Radio\Adapters; use App\Radio\Adapters;
use App\Settings;
use Azura\Logger;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Monolog\Logger;
use studio24\Rotate; use studio24\Rotate;
use Supervisor\Supervisor; use Supervisor\Supervisor;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
@ -20,22 +21,17 @@ class RotateLogs extends AbstractTask
/** @var Supervisor */ /** @var Supervisor */
protected $supervisor; protected $supervisor;
/** @var Logger */
protected $logger;
/** /**
* @param EntityManager $em * @param EntityManager $em
* @param Logger $logger
* @param Adapters $adapters * @param Adapters $adapters
* @param Supervisor $supervisor * @param Supervisor $supervisor
*/ */
public function __construct( public function __construct(
EntityManager $em, EntityManager $em,
Logger $logger,
Adapters $adapters, Adapters $adapters,
Supervisor $supervisor Supervisor $supervisor
) { ) {
parent::__construct($em, $logger); parent::__construct($em);
$this->adapters = $adapters; $this->adapters = $adapters;
$this->supervisor = $supervisor; $this->supervisor = $supervisor;
@ -51,7 +47,7 @@ class RotateLogs extends AbstractTask
if (!empty($stations)) { if (!empty($stations)) {
foreach ($stations as $station) { foreach ($stations as $station) {
/** @var Entity\Station $station */ /** @var Entity\Station $station */
$this->logger->info('Processing logs for station.', Logger::getInstance()->info('Processing logs for station.',
['id' => $station->getId(), 'name' => $station->getName()]); ['id' => $station->getId(), 'name' => $station->getName()]);
$this->rotateStationLogs($station); $this->rotateStationLogs($station);
@ -59,7 +55,7 @@ class RotateLogs extends AbstractTask
} }
// Rotate the main AzuraCast log. // Rotate the main AzuraCast log.
$rotate = new Rotate\Rotate(APP_INCLUDE_TEMP . '/app.log'); $rotate = new Rotate\Rotate(Settings::getInstance()->getTempDirectory() . '/app.log');
$rotate->keep(5); $rotate->keep(5);
$rotate->size('5MB'); $rotate->size('5MB');
$rotate->run(); $rotate->run();

View File

@ -213,27 +213,6 @@ class Utilities
return rmdir($source); return rmdir($source);
} }
/**
* Attempt to fetch the most likely "external" IP for this instance.
*
* @return false|string
*/
public static function getPublicIp()
{
if (APP_INSIDE_DOCKER) {
if (APP_IN_PRODUCTION) {
$public_ip = @file_get_contents('http://ipecho.net/plain');
if (!empty($public_ip)) {
return $public_ip;
}
}
return 'localhost';
}
return gethostbyname(gethostname()) ?? 'localhost';
}
/** /**
* Flatten an array from format: * Flatten an array from format:
* [ * [

View File

@ -1,7 +1,7 @@
<?php <?php
namespace App; namespace App;
use Azura\Settings; use App\Settings;
use DateTime; use DateTime;
use DateTimeZone; use DateTimeZone;
use Psr\SimpleCache\CacheInterface; use Psr\SimpleCache\CacheInterface;

View File

@ -4,6 +4,7 @@ namespace App\Webhook\Connector;
use App\Entity; use App\Entity;
use App\Event\SendWebhooks; use App\Event\SendWebhooks;
use App\Service\NChan; use App\Service\NChan;
use App\Settings;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use InfluxDB\Database; use InfluxDB\Database;
@ -111,7 +112,7 @@ class Local
// Write JSON file to disk so nginx can serve it without calling the PHP stack at all. // Write JSON file to disk so nginx can serve it without calling the PHP stack at all.
$this->logger->debug('Writing static nowplaying text file...'); $this->logger->debug('Writing static nowplaying text file...');
$static_np_dir = APP_INCLUDE_TEMP . '/nowplaying'; $static_np_dir = Settings::getInstance()->getTempDirectory() . '/nowplaying';
if (!is_dir($static_np_dir) && !mkdir($static_np_dir) && !is_dir($static_np_dir)) { if (!is_dir($static_np_dir) && !mkdir($static_np_dir) && !is_dir($static_np_dir)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $static_np_dir)); throw new RuntimeException(sprintf('Directory "%s" was not created', $static_np_dir));
} }

View File

@ -3,6 +3,7 @@ namespace App\Webhook;
use App\Entity; use App\Entity;
use App\Event\SendWebhooks; use App\Event\SendWebhooks;
use App\Settings;
use Azura\Exception; use Azura\Exception;
use InvalidArgumentException; use InvalidArgumentException;
use Monolog\Handler\TestHandler; use Monolog\Handler\TestHandler;
@ -33,7 +34,7 @@ class Dispatcher implements EventSubscriberInterface
public static function getSubscribedEvents() public static function getSubscribedEvents()
{ {
if (APP_TESTING_MODE) { if (Settings::getInstance()->isTesting()) {
return []; return [];
} }
@ -64,7 +65,7 @@ class Dispatcher implements EventSubscriberInterface
*/ */
public function dispatch(SendWebhooks $event): void public function dispatch(SendWebhooks $event): void
{ {
if (APP_TESTING_MODE) { if (Settings::getInstance()->isTesting()) {
$this->logger->info('In testing mode; no webhooks dispatched.'); $this->logger->info('In testing mode; no webhooks dispatched.');
return; return;
} }

View File

@ -66,7 +66,7 @@ $assets
<div class="card-body"> <div class="card-body">
<p class="card-text"><?=__('To restore a backup from your host computer, run:') ?></p> <p class="card-text"><?=__('To restore a backup from your host computer, run:') ?></p>
<?php if (APP_INSIDE_DOCKER): ?> <?php if (\App\Settings::getInstance()->isDocker()): ?>
<pre><code>./docker.sh restore path_to_backup.zip</code></pre> <pre><code>./docker.sh restore path_to_backup.zip</code></pre>
<?php else: ?> <?php else: ?>
<pre><code>/var/azuracast/www/bin/azuracast azuracast:restore path_to_backup.zip</code></pre> <pre><code>/var/azuracast/www/bin/azuracast azuracast:restore path_to_backup.zip</code></pre>

View File

@ -12,7 +12,7 @@ $this->layout('main', [
<h2 class="card-title"><?=__('System Logs') ?></h2> <h2 class="card-title"><?=__('System Logs') ?></h2>
</div> </div>
<div class="card-body"> <div class="card-body">
<?php if (APP_INSIDE_DOCKER): ?> <?php if (\App\Settings::getInstance()->isDocker()): ?>
<p><?=__('Because you are running Docker, some system logs can only be accessed from a shell session on the host computer. You can run <code>%s</code> to access container logs from the terminal.', 'docker-compose logs -f (nginx|web|stations|...)') ?></p> <p><?=__('Because you are running Docker, some system logs can only be accessed from a shell session on the host computer. You can run <code>%s</code> to access container logs from the terminal.', 'docker-compose logs -f (nginx|web|stations|...)') ?></p>
<?php endif; ?> <?php endif; ?>
</div> </div>

View File

@ -1,4 +1,3 @@
<!DOCTYPE html>
<?php <?php
/** /**
* @var \League\Plates\Template\Template $this * @var \League\Plates\Template\Template $this
@ -15,6 +14,7 @@
$user = $request->getUser(); $user = $request->getUser();
?> ?>
<!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
@ -148,7 +148,7 @@ echo $assets->js();
</section> </section>
<footer id="footer" <?php if (empty($sidebar)): ?>class="footer-alt"<?php endif; ?> role="contentinfo"> <footer id="footer" <?php if (empty($sidebar)): ?>class="footer-alt"<?php endif; ?> role="contentinfo">
<?=__('Powered by %s', '<a href="https://www.azuracast.com/" target="_blank">'.$settings['name'].'</a> &bull; '.$version->getVersionText().' &bull; '.(APP_INSIDE_DOCKER ? 'Docker' : 'Ansible').' &bull; PHP '.\PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION) ?><br> <?=__('Powered by %s', '<a href="https://www.azuracast.com/" target="_blank">'.$settings['name'].'</a> &bull; '.$version->getVersionText().' &bull; '.(\App\Settings::getInstance()->isDocker() ? 'Docker' : 'Ansible').' &bull; PHP '.\PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION) ?><br>
<?=__('Like our software? <a href="%s" target="_blank">Donate to support AzuraCast!</a>', 'https://www.azuracast.com/donate.html') ?> <?=__('Like our software? <a href="%s" target="_blank">Donate to support AzuraCast!</a>', 'https://www.azuracast.com/donate.html') ?>
</footer> </footer>

View File

@ -2,7 +2,8 @@
// Icons generated by: // Icons generated by:
// http://www.favicon-generator.org/ // http://www.favicon-generator.org/
$icon_base = '/static/icons/'.APP_APPLICATION_ENV; /** @var \App\Settings $settings */
$icon_base = '/static/icons/'.$settings[\App\Settings::APP_ENV];
?> ?>
<link rel="apple-touch-icon" sizes="180x180" href="<?=$icon_base ?>/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="<?=$icon_base ?>/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="<?=$icon_base ?>/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="<?=$icon_base ?>/favicon-32x32.png">

View File

@ -7,7 +7,7 @@
<p><?=__('If you\'re experiencing a bug or error, you can submit a GitHub issue using the link below.') ?></p> <p><?=__('If you\'re experiencing a bug or error, you can submit a GitHub issue using the link below.') ?></p>
<p><?=__('Your current installation type is <b>%s</b>. Be sure to include this when creating a new issue.', (APP_INSIDE_DOCKER ? 'Docker' : 'Ansible')) ?></p> <p><?=__('Your current installation type is <b>%s</b>. Be sure to include this when creating a new issue.', (\App\Settings::getInstance()->isDocker() ? 'Docker' : 'Ansible')) ?></p>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<a class="btn btn-outline-primary" role="button" href="https://github.com/AzuraCast/AzuraCast/issues/new/choose" target="_blank"> <a class="btn btn-outline-primary" role="button" href="https://github.com/AzuraCast/AzuraCast/issues/new/choose" target="_blank">

View File

@ -12,7 +12,7 @@ class C05_Station_AutomationCest extends CestAbstract
$I->wantTo('Test station automation.'); $I->wantTo('Test station automation.');
// Set up automation preconditions. // Set up automation preconditions.
$song_src = APP_INCLUDE_ROOT.'/resources/error.mp3'; $song_src = '/var/azuracast/www/resources/error.mp3';
$song_dest = $this->test_station->getRadioMediaDir().'/test.mp3'; $song_dest = $this->test_station->getRadioMediaDir().'/test.mp3';
copy($song_src, $song_dest); copy($song_src, $song_dest);

View File

@ -16,7 +16,7 @@ class D02_Api_RequestsCest extends CestAbstract
$this->em->flush(); $this->em->flush();
// Upload a test song. // Upload a test song.
$song_src = APP_INCLUDE_ROOT.'/resources/error.mp3'; $song_src = '/var/azuracast/www/resources/error.mp3';
$song_dest = $this->test_station->getRadioMediaDir().'/test.mp3'; $song_dest = $this->test_station->getRadioMediaDir().'/test.mp3';
copy($song_src, $song_dest); copy($song_src, $song_dest);

View File

@ -3,20 +3,17 @@
* PHPStan Bootstrap File * PHPStan Bootstrap File
*/ */
// Register gettext to avoid related errors error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT);
$translator = new \Gettext\Translator(); ini_set('display_errors', 1);
$translator->register();
// Define APP_ constants used by AzuraCast. $autoloader = require dirname(__DIR__).'/vendor/autoload.php';
define('APP_IS_COMMAND_LINE', true);
define('APP_INCLUDE_ROOT', dirname(__DIR__));
define('APP_INCLUDE_TEMP', dirname(APP_INCLUDE_ROOT).'/www_tmp');
define('APP_INSIDE_DOCKER', true); $app = App\AppFactory::create($autoloader, [
define('APP_DOCKER_REVISION', 1); Azura\Settings::BASE_DIR => dirname(__DIR__),
]);
define('APP_TESTING_MODE', true); $di = $app->getContainer();
define('SAMPLE_TIMESTAMP', rand(time() - 86400, time() + 86400));
define('APP_APPLICATION_ENV', 'testing'); /** @var App\Customization $customization */
define('APP_IN_PRODUCTION', false); $customization = $di->get(App\Customization::class);
$customization->init();