Warn about sync tasks not having been run recently.
Also includes a minor rewrite of the EventDispatcher, and a restructure of notification checks into standalone classes.
This commit is contained in:
parent
5cab595bcf
commit
582b8faef9
|
@ -6,60 +6,61 @@ use App\Middleware;
|
|||
use App\Settings;
|
||||
|
||||
return function (App\EventDispatcher $dispatcher) {
|
||||
$dispatcher->addListener(Event\BuildConsoleCommands::class, function (Event\BuildConsoleCommands $event) use ($dispatcher) {
|
||||
$console = $event->getConsole();
|
||||
$di = $console->getContainer();
|
||||
$dispatcher->addListener(Event\BuildConsoleCommands::class,
|
||||
function (Event\BuildConsoleCommands $event) use ($dispatcher) {
|
||||
$console = $event->getConsole();
|
||||
$di = $console->getContainer();
|
||||
|
||||
/** @var Settings $settings */
|
||||
$settings = $di->get(Settings::class);
|
||||
/** @var Settings $settings */
|
||||
$settings = $di->get(Settings::class);
|
||||
|
||||
if ($settings->enableRedis()) {
|
||||
$console->command('cache:clear', Command\ClearCacheCommand::class)
|
||||
->setDescription('Clear all application caches.');
|
||||
}
|
||||
if ($settings->enableRedis()) {
|
||||
$console->command('cache:clear', Command\ClearCacheCommand::class)
|
||||
->setDescription('Clear all application caches.');
|
||||
}
|
||||
|
||||
if ($settings->enableDatabase()) {
|
||||
// Doctrine ORM/DBAL
|
||||
Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($console);
|
||||
if ($settings->enableDatabase()) {
|
||||
// Doctrine ORM/DBAL
|
||||
Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($console);
|
||||
|
||||
// Add Doctrine Migrations
|
||||
/** @var Doctrine\ORM\EntityManagerInterface $em */
|
||||
$em = $di->get(Doctrine\ORM\EntityManagerInterface::class);
|
||||
// Add Doctrine Migrations
|
||||
/** @var Doctrine\ORM\EntityManagerInterface $em */
|
||||
$em = $di->get(Doctrine\ORM\EntityManagerInterface::class);
|
||||
|
||||
$helper_set = $console->getHelperSet();
|
||||
$doctrine_helpers = Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
|
||||
$helper_set->set($doctrine_helpers->get('db'), 'db');
|
||||
$helper_set->set($doctrine_helpers->get('em'), 'em');
|
||||
$helper_set = $console->getHelperSet();
|
||||
$doctrine_helpers = Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($em);
|
||||
$helper_set->set($doctrine_helpers->get('db'), 'db');
|
||||
$helper_set->set($doctrine_helpers->get('em'), 'em');
|
||||
|
||||
$migrationConfigurations = [
|
||||
'migrations_paths' => [
|
||||
'App\Entity\Migration' => $settings[Settings::BASE_DIR] . '/src/Entity/Migration',
|
||||
],
|
||||
'table_storage' => [
|
||||
'table_name' => 'app_migrations',
|
||||
'version_column_length' => 191,
|
||||
],
|
||||
];
|
||||
$migrationConfigurations = [
|
||||
'migrations_paths' => [
|
||||
'App\Entity\Migration' => $settings[Settings::BASE_DIR] . '/src/Entity/Migration',
|
||||
],
|
||||
'table_storage' => [
|
||||
'table_name' => 'app_migrations',
|
||||
'version_column_length' => 191,
|
||||
],
|
||||
];
|
||||
|
||||
$buildMigrationConfigurationsEvent = new Event\BuildMigrationConfigurationArray(
|
||||
$migrationConfigurations,
|
||||
$settings[Settings::BASE_DIR]
|
||||
);
|
||||
$dispatcher->dispatch($buildMigrationConfigurationsEvent);
|
||||
$buildMigrationConfigurationsEvent = new Event\BuildMigrationConfigurationArray(
|
||||
$migrationConfigurations,
|
||||
$settings[Settings::BASE_DIR]
|
||||
);
|
||||
$dispatcher->dispatch($buildMigrationConfigurationsEvent);
|
||||
|
||||
$migrationConfigurations = $buildMigrationConfigurationsEvent->getMigrationConfigurations();
|
||||
$migrationConfigurations = $buildMigrationConfigurationsEvent->getMigrationConfigurations();
|
||||
|
||||
$migrateConfig = new Doctrine\Migrations\Configuration\Migration\ConfigurationArray($migrationConfigurations);
|
||||
$migrateConfig = new Doctrine\Migrations\Configuration\Migration\ConfigurationArray($migrationConfigurations);
|
||||
|
||||
$migrateFactory = Doctrine\Migrations\DependencyFactory::fromEntityManager(
|
||||
$migrateConfig,
|
||||
new Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager($em)
|
||||
);
|
||||
Doctrine\Migrations\Tools\Console\ConsoleRunner::addCommands($console, $migrateFactory);
|
||||
}
|
||||
$migrateFactory = Doctrine\Migrations\DependencyFactory::fromEntityManager(
|
||||
$migrateConfig,
|
||||
new Doctrine\Migrations\Configuration\EntityManager\ExistingEntityManager($em)
|
||||
);
|
||||
Doctrine\Migrations\Tools\Console\ConsoleRunner::addCommands($console, $migrateFactory);
|
||||
}
|
||||
|
||||
call_user_func(include(__DIR__ . '/cli.php'), $console);
|
||||
});
|
||||
call_user_func(include(__DIR__ . '/cli.php'), $console);
|
||||
});
|
||||
|
||||
$dispatcher->addListener(Event\BuildRoutes::class, function (Event\BuildRoutes $event) {
|
||||
$app = $event->getApp();
|
||||
|
@ -115,15 +116,35 @@ return function (App\EventDispatcher $dispatcher) {
|
|||
});
|
||||
|
||||
// Other event subscribers from across the application.
|
||||
$dispatcher->addCallableListener(
|
||||
Event\GetSyncTasks::class,
|
||||
App\Sync\TaskLocator::class
|
||||
);
|
||||
|
||||
$dispatcher->addCallableListener(
|
||||
Event\GetNotifications::class,
|
||||
App\Notification\Check\ComposeVersionCheck::class
|
||||
);
|
||||
$dispatcher->addCallableListener(
|
||||
Event\GetNotifications::class,
|
||||
App\Notification\Check\UpdateCheck::class
|
||||
);
|
||||
$dispatcher->addCallableListener(
|
||||
Event\GetNotifications::class,
|
||||
App\Notification\Check\RecentBackupCheck::class
|
||||
);
|
||||
$dispatcher->addCallableListener(
|
||||
Event\GetNotifications::class,
|
||||
App\Notification\Check\SyncTaskCheck::class
|
||||
);
|
||||
|
||||
$dispatcher->addServiceSubscriber([
|
||||
App\Radio\AutoDJ\Queue::class,
|
||||
App\Radio\AutoDJ\Annotations::class,
|
||||
App\Radio\Backend\Liquidsoap\ConfigWriter::class,
|
||||
App\Sync\Task\NowPlaying::class,
|
||||
App\Sync\TaskLocator::class,
|
||||
App\Webhook\Dispatcher::class,
|
||||
App\Controller\Api\NowplayingController::class,
|
||||
App\Notification\Manager::class,
|
||||
]);
|
||||
|
||||
};
|
||||
|
|
|
@ -70,7 +70,7 @@ class DashboardController
|
|||
}
|
||||
|
||||
// Get administrator notifications.
|
||||
$notification_event = new Event\GetNotifications($user, $request);
|
||||
$notification_event = new Event\GetNotifications($request);
|
||||
$this->dispatcher->dispatch($notification_event);
|
||||
|
||||
$notifications = $notification_event->getNotifications();
|
||||
|
|
|
@ -2,32 +2,22 @@
|
|||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Notification\Notification;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
class GetNotifications extends Event
|
||||
{
|
||||
protected User $current_user;
|
||||
|
||||
protected ServerRequest $request;
|
||||
|
||||
protected array $notifications;
|
||||
|
||||
public function __construct(User $current_user, ServerRequest $request)
|
||||
public function __construct(ServerRequest $request)
|
||||
{
|
||||
$this->current_user = $current_user;
|
||||
$this->request = $request;
|
||||
|
||||
$this->notifications = [];
|
||||
}
|
||||
|
||||
public function getCurrentUser(): User
|
||||
{
|
||||
return $this->current_user;
|
||||
}
|
||||
|
||||
|
||||
public function getRequest(): ServerRequest
|
||||
{
|
||||
return $this->request;
|
||||
|
|
|
@ -18,29 +18,38 @@ class EventDispatcher extends \Symfony\Component\EventDispatcher\EventDispatcher
|
|||
$this->callableResolver = $callableResolver;
|
||||
}
|
||||
|
||||
public function addServiceSubscriber($class_name): void
|
||||
/**
|
||||
* @param class-string|class-string[] $className
|
||||
*/
|
||||
public function addServiceSubscriber($className): void
|
||||
{
|
||||
if (is_array($class_name)) {
|
||||
foreach ($class_name as $service) {
|
||||
if (is_array($className)) {
|
||||
foreach ($className as $service) {
|
||||
$this->addServiceSubscriber($service);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($class_name::getSubscribedEvents() as $eventName => $params) {
|
||||
foreach ($className::getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_string($params)) {
|
||||
$this->addListener($eventName, $this->getCallable($class_name, $params));
|
||||
} elseif (is_string($params[0])) {
|
||||
$this->addListener(
|
||||
$this->addCallableListener(
|
||||
$eventName,
|
||||
$this->getCallable($class_name, $params[0]),
|
||||
$className,
|
||||
$params
|
||||
);
|
||||
} elseif (is_string($params[0])) {
|
||||
$this->addCallableListener(
|
||||
$eventName,
|
||||
$className,
|
||||
$params[0],
|
||||
$params[1] ?? 0
|
||||
);
|
||||
} else {
|
||||
foreach ($params as $listener) {
|
||||
$this->addListener(
|
||||
$this->addCallableListener(
|
||||
$eventName,
|
||||
$this->getCallable($class_name, $listener[0]),
|
||||
$className,
|
||||
$listener[0],
|
||||
$listener[1] ?? 0
|
||||
);
|
||||
}
|
||||
|
@ -48,31 +57,65 @@ class EventDispatcher extends \Symfony\Component\EventDispatcher\EventDispatcher
|
|||
}
|
||||
}
|
||||
|
||||
public function removeServiceSubscriber($class_name): void
|
||||
/**
|
||||
* @param class-string|class-string[] $className
|
||||
*/
|
||||
public function removeServiceSubscriber($className): void
|
||||
{
|
||||
if (is_array($class_name)) {
|
||||
foreach ($class_name as $service) {
|
||||
if (is_array($className)) {
|
||||
foreach ($className as $service) {
|
||||
$this->removeServiceSubscriber($service);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($class_name::getSubscribedEvents() as $eventName => $params) {
|
||||
foreach ($className::getSubscribedEvents() as $eventName => $params) {
|
||||
if (is_array($params) && is_array($params[0])) {
|
||||
foreach ($params as $listener) {
|
||||
$this->removeListener($eventName, $this->getCallable($class_name, $listener[0]));
|
||||
$this->removeCallableListener(
|
||||
$eventName,
|
||||
$className,
|
||||
$listener[0]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$this->removeListener(
|
||||
$this->removeCallableListener(
|
||||
$eventName,
|
||||
$this->getCallable($class_name, is_string($params) ? $params : $params[0])
|
||||
$className,
|
||||
is_string($params) ? $params : $params[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getCallable($class_name, $method): DeferredCallable
|
||||
{
|
||||
return new DeferredCallable($class_name . ':' . $method, $this->callableResolver);
|
||||
public function addCallableListener(
|
||||
string $eventName,
|
||||
string $className,
|
||||
?string $method = '__invoke',
|
||||
int $priority = 0
|
||||
): void {
|
||||
$this->addListener(
|
||||
$eventName,
|
||||
$this->getCallable($className, $method),
|
||||
$priority
|
||||
);
|
||||
}
|
||||
|
||||
public function removeCallableListener(
|
||||
string $eventName,
|
||||
string $className,
|
||||
?string $method = '__invoke'
|
||||
): void {
|
||||
$this->removeListener(
|
||||
$eventName,
|
||||
$this->getCallable($className, $method)
|
||||
);
|
||||
}
|
||||
|
||||
protected function getCallable(
|
||||
string $className,
|
||||
?string $method = '__invoke'
|
||||
): DeferredCallable {
|
||||
return new DeferredCallable($className . ':' . $method, $this->callableResolver);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notification\Check;
|
||||
|
||||
use App\Acl;
|
||||
use App\Event\GetNotifications;
|
||||
use App\Notification\Notification;
|
||||
use App\Settings;
|
||||
|
||||
class ComposeVersionCheck
|
||||
{
|
||||
protected Settings $appSettings;
|
||||
|
||||
public function __construct(Settings $appSettings)
|
||||
{
|
||||
$this->appSettings = $appSettings;
|
||||
}
|
||||
|
||||
public function __invoke(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for full administrators only.
|
||||
$request = $event->getRequest();
|
||||
$acl = $request->getAcl();
|
||||
if (!$acl->userAllowed($request->getUser(), Acl::GLOBAL_ALL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->appSettings->isDocker()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compose_revision = $_ENV['AZURACAST_DC_REVISION'] ?? 1;
|
||||
|
||||
if ($compose_revision < 5) {
|
||||
$event->addNotification(new Notification(
|
||||
__('Your <code>docker-compose.yml</code> file is out of date!'),
|
||||
// phpcs:disable Generic.Files.LineLength
|
||||
__(
|
||||
'You should update your <code>docker-compose.yml</code> file to reflect the newest changes. View the <a href="%s" target="_blank">latest version of the file</a> and update your file accordingly.<br>You can also use the <code>./docker.sh</code> utility script to automatically update your file.',
|
||||
'https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/docker-compose.sample.yml'
|
||||
),
|
||||
// phpcs:enable
|
||||
Notification::WARNING
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notification\Check;
|
||||
|
||||
use App\Acl;
|
||||
use App\Entity;
|
||||
use App\Event\GetNotifications;
|
||||
use App\Notification\Notification;
|
||||
use App\Settings;
|
||||
use Carbon\CarbonImmutable;
|
||||
|
||||
class RecentBackupCheck
|
||||
{
|
||||
protected Entity\Repository\SettingsRepository $settingsRepo;
|
||||
|
||||
protected Settings $appSettings;
|
||||
|
||||
public function __construct(Entity\Repository\SettingsRepository $settingsRepo, Settings $appSettings)
|
||||
{
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->appSettings = $appSettings;
|
||||
}
|
||||
|
||||
public function __invoke(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for backup administrators only.
|
||||
$request = $event->getRequest();
|
||||
$acl = $request->getAcl();
|
||||
if (!$acl->userAllowed($request->getUser(), Acl::GLOBAL_BACKUPS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->appSettings->isProduction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$threshold = CarbonImmutable::now()->subWeeks(2)->getTimestamp();
|
||||
$backupLastRun = $this->settingsRepo->getSetting(Entity\Settings::BACKUP_LAST_RUN, 0);
|
||||
|
||||
if ($backupLastRun < $threshold) {
|
||||
$router = $request->getRouter();
|
||||
$backupUrl = $router->named('admin:backups:index');
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('Installation Not Recently Backed Up'),
|
||||
// phpcs:disable Generic.Files.LineLength
|
||||
__(
|
||||
'This installation has not been backed up in the last two weeks. Visit the <a href="%s" target="_blank">Backups</a> page to run a new backup.',
|
||||
$backupUrl
|
||||
),
|
||||
// phpcs:enable
|
||||
Notification::INFO
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notification\Check;
|
||||
|
||||
use App\Acl;
|
||||
use App\Event\GetNotifications;
|
||||
use App\Notification\Notification;
|
||||
use App\Sync\Runner;
|
||||
|
||||
class SyncTaskCheck
|
||||
{
|
||||
protected Runner $syncRunner;
|
||||
|
||||
public function __construct(Runner $syncRunner)
|
||||
{
|
||||
$this->syncRunner = $syncRunner;
|
||||
}
|
||||
|
||||
public function __invoke(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for full administrators only.
|
||||
$request = $event->getRequest();
|
||||
$acl = $request->getAcl();
|
||||
if (!$acl->userAllowed($request->getUser(), Acl::GLOBAL_ALL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$syncTasks = $this->syncRunner->getSyncTimes();
|
||||
|
||||
foreach ($syncTasks as $taskKey => $task) {
|
||||
$interval = $task['interval'];
|
||||
$diff = $task['diff'];
|
||||
|
||||
if ($diff > ($interval * 5)) {
|
||||
$router = $request->getRouter();
|
||||
$backupUrl = $router->named('admin:debug:sync', ['type' => $taskKey]);
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('Synchronized Task Not Recently Run'),
|
||||
// phpcs:disable Generic.Files.LineLength
|
||||
__(
|
||||
'The "%s" synchronization task has not run recently. This may indicate an error with your installation. <a href="%s" target="_blank">Manually run the task</a> to check for errors.',
|
||||
$task['name'],
|
||||
$backupUrl
|
||||
),
|
||||
// phpcs:enable
|
||||
Notification::ERROR
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notification\Check;
|
||||
|
||||
use App\Acl;
|
||||
use App\Entity;
|
||||
use App\Event\GetNotifications;
|
||||
use App\Notification\Notification;
|
||||
use App\Version;
|
||||
|
||||
class UpdateCheck
|
||||
{
|
||||
protected Entity\Repository\SettingsRepository $settingsRepo;
|
||||
|
||||
protected Version $version;
|
||||
|
||||
public function __construct(Entity\Repository\SettingsRepository $settingsRepo, Version $version)
|
||||
{
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
public function __invoke(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for full administrators only.
|
||||
$request = $event->getRequest();
|
||||
$acl = $request->getAcl();
|
||||
if (!$acl->userAllowed($request->getUser(), Acl::GLOBAL_ALL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$checkForUpdates = (bool)$this->settingsRepo->getSetting(Entity\Settings::CENTRAL_UPDATES, 1);
|
||||
if (!$checkForUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
$updateData = $this->settingsRepo->getSetting(Entity\Settings::UPDATE_RESULTS);
|
||||
if (empty($updateData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instructions_url = 'https://www.azuracast.com/administration/system/updating.html';
|
||||
$instructions_string = __(
|
||||
'Follow the <a href="%s" target="_blank">update instructions</a> to update your installation.',
|
||||
$instructions_url
|
||||
);
|
||||
|
||||
$releaseChannel = $this->version->getReleaseChannel();
|
||||
|
||||
if (Version::RELEASE_CHANNEL_STABLE === $releaseChannel && $updateData['needs_release_update']) {
|
||||
$notification_parts = [
|
||||
'<b>' . __(
|
||||
'AzuraCast <a href="%s" target="_blank">version %s</a> is now available.',
|
||||
'https://github.com/AzuraCast/AzuraCast/releases',
|
||||
$updateData['latest_release']
|
||||
) . '</b>',
|
||||
__(
|
||||
'You are currently running version %s. Updating is highly recommended.',
|
||||
$updateData['current_release']
|
||||
),
|
||||
$instructions_string,
|
||||
];
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('New AzuraCast Release Version Available'),
|
||||
implode(' ', $notification_parts),
|
||||
Notification::INFO
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Version::RELEASE_CHANNEL_ROLLING === $releaseChannel && $updateData['needs_rolling_update']) {
|
||||
$notification_parts = [];
|
||||
if ($updateData['rolling_updates_available'] < 15 && !empty($updateData['rolling_updates_list'])) {
|
||||
$notification_parts[] = __('The following improvements have been made since your last update:');
|
||||
$notification_parts[] = nl2br('<ul><li>' . implode(
|
||||
'</li><li>',
|
||||
$updateData['rolling_updates_list']
|
||||
) . '</li></ul>');
|
||||
} else {
|
||||
$notification_parts[] = '<b>' . __(
|
||||
'Your installation is currently %d update(s) behind the latest version.',
|
||||
$updateData['rolling_updates_available']
|
||||
) . '</b>';
|
||||
$notification_parts[] = __('You should update to take advantage of bug and security fixes.');
|
||||
}
|
||||
|
||||
$notification_parts[] = $instructions_string;
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('New AzuraCast Updates Available'),
|
||||
implode(' ', $notification_parts),
|
||||
Notification::INFO
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Notification;
|
||||
|
||||
use App\Acl;
|
||||
use App\Entity;
|
||||
use App\Event\GetNotifications;
|
||||
use App\Settings;
|
||||
use App\Version;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Monolog\Logger;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class Manager implements EventSubscriberInterface
|
||||
{
|
||||
protected Acl $acl;
|
||||
|
||||
protected EntityManagerInterface $em;
|
||||
|
||||
protected Logger $logger;
|
||||
|
||||
protected Entity\Repository\SettingsRepository $settingsRepo;
|
||||
|
||||
protected Settings $appSettings;
|
||||
|
||||
protected Version $version;
|
||||
|
||||
public function __construct(
|
||||
Acl $acl,
|
||||
EntityManagerInterface $em,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Logger $logger,
|
||||
Settings $appSettings,
|
||||
Version $version
|
||||
) {
|
||||
$this->acl = $acl;
|
||||
$this->em = $em;
|
||||
$this->logger = $logger;
|
||||
$this->appSettings = $appSettings;
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
GetNotifications::class => [
|
||||
['checkComposeVersion', 1],
|
||||
['checkUpdates', 0],
|
||||
['checkRecentBackup', -1],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function checkComposeVersion(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for full administrators only.
|
||||
if (!$this->acl->userAllowed($event->getCurrentUser(), Acl::GLOBAL_ALL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->appSettings->isDocker()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compose_revision = $_ENV['AZURACAST_DC_REVISION'] ?? 1;
|
||||
|
||||
if ($compose_revision < 5) {
|
||||
$event->addNotification(new Notification(
|
||||
__('Your <code>docker-compose.yml</code> file is out of date!'),
|
||||
// phpcs:disable Generic.Files.LineLength
|
||||
__(
|
||||
'You should update your <code>docker-compose.yml</code> file to reflect the newest changes. View the <a href="%s" target="_blank">latest version of the file</a> and update your file accordingly.<br>You can also use the <code>./docker.sh</code> utility script to automatically update your file.',
|
||||
'https://raw.githubusercontent.com/AzuraCast/AzuraCast/master/docker-compose.sample.yml'
|
||||
),
|
||||
// phpcs:enable
|
||||
Notification::WARNING
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public function checkUpdates(GetNotifications $event): void
|
||||
{
|
||||
// This notification is for full administrators only.
|
||||
if (!$this->acl->userAllowed($event->getCurrentUser(), Acl::GLOBAL_ALL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$checkForUpdates = (bool)$this->settingsRepo->getSetting(Entity\Settings::CENTRAL_UPDATES, 1);
|
||||
if (!$checkForUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
$updateData = $this->settingsRepo->getSetting(Entity\Settings::UPDATE_RESULTS);
|
||||
if (empty($updateData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$instructions_url = 'https://www.azuracast.com/administration/system/updating.html';
|
||||
$instructions_string = __(
|
||||
'Follow the <a href="%s" target="_blank">update instructions</a> to update your installation.',
|
||||
$instructions_url
|
||||
);
|
||||
|
||||
$releaseChannel = $this->version->getReleaseChannel();
|
||||
|
||||
if (Version::RELEASE_CHANNEL_STABLE === $releaseChannel && $updateData['needs_release_update']) {
|
||||
$notification_parts = [
|
||||
'<b>' . __(
|
||||
'AzuraCast <a href="%s" target="_blank">version %s</a> is now available.',
|
||||
'https://github.com/AzuraCast/AzuraCast/releases',
|
||||
$updateData['latest_release']
|
||||
) . '</b>',
|
||||
__(
|
||||
'You are currently running version %s. Updating is highly recommended.',
|
||||
$updateData['current_release']
|
||||
),
|
||||
$instructions_string,
|
||||
];
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('New AzuraCast Release Version Available'),
|
||||
implode(' ', $notification_parts),
|
||||
Notification::INFO
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Version::RELEASE_CHANNEL_ROLLING === $releaseChannel && $updateData['needs_rolling_update']) {
|
||||
$notification_parts = [];
|
||||
if ($updateData['rolling_updates_available'] < 15 && !empty($updateData['rolling_updates_list'])) {
|
||||
$notification_parts[] = __('The following improvements have been made since your last update:');
|
||||
$notification_parts[] = nl2br('<ul><li>' . implode(
|
||||
'</li><li>',
|
||||
$updateData['rolling_updates_list']
|
||||
) . '</li></ul>');
|
||||
} else {
|
||||
$notification_parts[] = '<b>' . __(
|
||||
'Your installation is currently %d update(s) behind the latest version.',
|
||||
$updateData['rolling_updates_available']
|
||||
) . '</b>';
|
||||
$notification_parts[] = __('You should update to take advantage of bug and security fixes.');
|
||||
}
|
||||
|
||||
$notification_parts[] = $instructions_string;
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('New AzuraCast Updates Available'),
|
||||
implode(' ', $notification_parts),
|
||||
Notification::INFO
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function checkRecentBackup(GetNotifications $event): void
|
||||
{
|
||||
if (!$this->acl->userAllowed($event->getCurrentUser(), Acl::GLOBAL_BACKUPS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->appSettings->isProduction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$threshold = CarbonImmutable::now()->subWeeks(2)->getTimestamp();
|
||||
$backupLastRun = $this->settingsRepo->getSetting(Entity\Settings::BACKUP_LAST_RUN, 0);
|
||||
|
||||
if ($backupLastRun < $threshold) {
|
||||
$router = $event->getRequest()->getRouter();
|
||||
|
||||
$backupUrl = $router->named('admin:backups:index');
|
||||
|
||||
$event->addNotification(new Notification(
|
||||
__('Installation Not Recently Backed Up'),
|
||||
// phpcs:disable Generic.Files.LineLength
|
||||
__(
|
||||
'This installation has not been backed up in the last two weeks. Visit the <a href="%s" target="_blank">Backups</a> page to run a new backup.',
|
||||
$backupUrl
|
||||
),
|
||||
// phpcs:enable
|
||||
Notification::INFO
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -149,6 +149,7 @@ class Runner
|
|||
],
|
||||
'lastRunSetting' => Entity\Settings::NOWPLAYING_LAST_RUN,
|
||||
'timeout' => 600,
|
||||
'interval' => 15,
|
||||
],
|
||||
GetSyncTasks::SYNC_SHORT => [
|
||||
'name' => __('1-Minute Sync'),
|
||||
|
@ -157,6 +158,7 @@ class Runner
|
|||
],
|
||||
'lastRunSetting' => Entity\Settings::SHORT_SYNC_LAST_RUN,
|
||||
'timeout' => 600,
|
||||
'interval' => 60,
|
||||
],
|
||||
GetSyncTasks::SYNC_MEDIUM => [
|
||||
'name' => __('5-Minute Sync'),
|
||||
|
@ -165,6 +167,7 @@ class Runner
|
|||
],
|
||||
'lastRunSetting' => Entity\Settings::MEDIUM_SYNC_LAST_RUN,
|
||||
'timeout' => 600,
|
||||
'interval' => 300,
|
||||
],
|
||||
GetSyncTasks::SYNC_LONG => [
|
||||
'name' => __('1-Hour Sync'),
|
||||
|
@ -174,6 +177,7 @@ class Runner
|
|||
],
|
||||
'lastRunSetting' => Entity\Settings::LONG_SYNC_LAST_RUN,
|
||||
'timeout' => 1800,
|
||||
'interval' => 3600,
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -4,10 +4,8 @@ namespace App\Sync;
|
|||
|
||||
use App\Event\GetSyncTasks;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
class TaskLocator implements EventSubscriberInterface
|
||||
class TaskLocator
|
||||
{
|
||||
protected ContainerInterface $di;
|
||||
|
||||
|
@ -19,19 +17,7 @@ class TaskLocator implements EventSubscriberInterface
|
|||
$this->tasks = $tasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
GetSyncTasks::class => [
|
||||
['assignTasks', 0],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function assignTasks(GetSyncTasks $event): void
|
||||
public function __invoke(GetSyncTasks $event): void
|
||||
{
|
||||
$type = $event->getType();
|
||||
if (!isset($this->tasks[$type])) {
|
||||
|
|
Loading…
Reference in New Issue