Remove string-to-Uri-to-string in many places; update to take advantage of Slim Router perf update.

This commit is contained in:
Buster Neece 2022-11-06 14:42:50 -06:00
parent 2d168c00bb
commit 9d915aba3c
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
102 changed files with 428 additions and 433 deletions

20
composer.lock generated
View File

@ -6332,16 +6332,16 @@
},
{
"name": "slim/slim",
"version": "4.10.0",
"version": "4.11.0",
"source": {
"type": "git",
"url": "https://github.com/slimphp/Slim.git",
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0"
"reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
"reference": "0dfc7d2fdf2553b361d864d51af3fe8a6ad168b0",
"url": "https://api.github.com/repos/slimphp/Slim/zipball/b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7",
"reference": "b0f4ca393ea037be9ac7292ba7d0a34d18bac0c7",
"shasum": ""
},
"require": {
@ -6356,21 +6356,21 @@
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"require-dev": {
"adriansuter/php-autoload-override": "^1.2",
"adriansuter/php-autoload-override": "^1.3",
"ext-simplexml": "*",
"guzzlehttp/psr7": "^2.1",
"guzzlehttp/psr7": "^2.4",
"httpsoft/http-message": "^1.0",
"httpsoft/http-server-request": "^1.0",
"laminas/laminas-diactoros": "^2.8",
"laminas/laminas-diactoros": "^2.17",
"nyholm/psr7": "^1.5",
"nyholm/psr7-server": "^1.0",
"phpspec/prophecy": "^1.15",
"phpspec/prophecy-phpunit": "^2.0",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan": "^1.8",
"phpunit/phpunit": "^9.5",
"slim/http": "^1.2",
"slim/psr7": "^1.5",
"squizlabs/php_codesniffer": "^3.6"
"squizlabs/php_codesniffer": "^3.7"
},
"suggest": {
"ext-simplexml": "Needed to support XML format in BodyParsingMiddleware",
@ -6443,7 +6443,7 @@
"type": "tidelift"
}
],
"time": "2022-03-14T14:18:23+00:00"
"time": "2022-11-06T16:33:39+00:00"
},
{
"name": "spatie/dropbox-api",

View File

@ -5,7 +5,7 @@
use App\Enums\GlobalPermissions;
return function (App\Event\BuildAdminMenu $e) {
return static function (App\Event\BuildAdminMenu $e) {
$request = $e->getRequest();
$router = $request->getRouter();
@ -13,36 +13,36 @@ return function (App\Event\BuildAdminMenu $e) {
[
'maintenance' => [
'label' => __('System Maintenance'),
'icon' => 'router',
'icon' => 'router',
'items' => [
'settings' => [
'label' => __('System Settings'),
'url' => (string)$router->named('admin:settings:index'),
'settings' => [
'label' => __('System Settings'),
'url' => $router->named('admin:settings:index'),
'permission' => GlobalPermissions::Settings,
],
'branding' => [
'label' => __('Custom Branding'),
'url' => (string)$router->named('admin:branding:index'),
'branding' => [
'label' => __('Custom Branding'),
'url' => $router->named('admin:branding:index'),
'permission' => GlobalPermissions::Settings,
],
'logs' => [
'label' => __('System Logs'),
'url' => (string)$router->named('admin:logs:index'),
'logs' => [
'label' => __('System Logs'),
'url' => $router->named('admin:logs:index'),
'permission' => GlobalPermissions::Logs,
],
'storage_locations' => [
'label' => __('Storage Locations'),
'url' => (string)$router->named('admin:storage_locations:index'),
'label' => __('Storage Locations'),
'url' => $router->named('admin:storage_locations:index'),
'permission' => GlobalPermissions::StorageLocations,
],
'backups' => [
'label' => __('Backups'),
'url' => (string)$router->named('admin:backups:index'),
'label' => __('Backups'),
'url' => $router->named('admin:backups:index'),
'permission' => GlobalPermissions::Backups,
],
'debug' => [
'label' => __('System Debugger'),
'url' => (string)$router->named('admin:debug:index'),
'label' => __('System Debugger'),
'url' => $router->named('admin:debug:index'),
'permission' => GlobalPermissions::All,
],
],
@ -52,23 +52,23 @@ return function (App\Event\BuildAdminMenu $e) {
'icon' => 'group',
'items' => [
'manage_users' => [
'label' => __('User Accounts'),
'url' => (string)$router->named('admin:users:index'),
'label' => __('User Accounts'),
'url' => $router->named('admin:users:index'),
'permission' => GlobalPermissions::All,
],
'permissions' => [
'label' => __('Roles & Permissions'),
'url' => (string)$router->named('admin:permissions:index'),
'label' => __('Roles & Permissions'),
'url' => $router->named('admin:permissions:index'),
'permission' => GlobalPermissions::All,
],
'auditlog' => [
'label' => __('Audit Log'),
'url' => (string)$router->named('admin:auditlog:index'),
'label' => __('Audit Log'),
'url' => $router->named('admin:auditlog:index'),
'permission' => GlobalPermissions::Logs,
],
'api_keys' => [
'label' => __('API Keys'),
'url' => (string)$router->named('admin:api:index'),
'label' => __('API Keys'),
'url' => $router->named('admin:api:index'),
'permission' => GlobalPermissions::ApiKeys,
],
],
@ -78,33 +78,33 @@ return function (App\Event\BuildAdminMenu $e) {
'icon' => 'volume_up',
'items' => [
'manage_stations' => [
'label' => __('Stations'),
'url' => (string)$router->named('admin:stations:index'),
'label' => __('Stations'),
'url' => $router->named('admin:stations:index'),
'permission' => GlobalPermissions::Stations,
],
'custom_fields' => [
'label' => __('Custom Fields'),
'url' => (string)$router->named('admin:custom_fields:index'),
'label' => __('Custom Fields'),
'url' => $router->named('admin:custom_fields:index'),
'permission' => GlobalPermissions::CustomFields,
],
'relays' => [
'label' => __('Connected AzuraRelays'),
'url' => (string)$router->named('admin:relays:index'),
'url' => $router->named('admin:relays:index'),
'permission' => GlobalPermissions::Stations,
],
'shoutcast' => [
'label' => __('Install Shoutcast'),
'url' => (string)$router->named('admin:install_shoutcast:index'),
'url' => $router->named('admin:install_shoutcast:index'),
'permission' => GlobalPermissions::All,
],
'stereo_tool' => [
'label' => __('Install Stereo Tool'),
'url' => (string)$router->named('admin:install_stereo_tool:index'),
'url' => $router->named('admin:install_stereo_tool:index'),
'permission' => GlobalPermissions::All,
],
'geolite' => [
'label' => __('Install GeoLite IP Database'),
'url' => (string)$router->named('admin:install_geolite:index'),
'url' => $router->named('admin:install_geolite:index'),
'permission' => GlobalPermissions::All,
],
],

View File

@ -7,7 +7,7 @@ use App\Enums\StationFeatures;
use App\Enums\StationPermissions;
use App\Radio\Enums\AudioProcessingMethods;
return function (App\Event\BuildStationMenu $e) {
return static function (App\Event\BuildStationMenu $e) {
$request = $e->getRequest();
$station = $e->getStation();
@ -32,7 +32,7 @@ return function (App\Event\BuildStationMenu $e) {
'label' => __('Start Station'),
'title' => __('Ready to start broadcasting? Click to start your station.'),
'icon' => 'refresh',
'url' => (string)$router->fromHere('api:stations:reload'),
'url' => $router->fromHere('api:stations:reload'),
'class' => 'api-call text-success',
'confirm' => $reloadMessage,
'visible' => $hasLocalServices && !$station->getHasStarted(),
@ -42,7 +42,7 @@ return function (App\Event\BuildStationMenu $e) {
'label' => __('Reload to Apply Changes'),
'title' => __('Click to restart your station and apply configuration changes.'),
'icon' => 'refresh',
'url' => (string)$router->fromHere('api:stations:reload'),
'url' => $router->fromHere('api:stations:reload'),
'class' => 'api-call text-warning btn-restart-station '
. (!$station->getNeedsRestart() ? 'd-none' : ''),
'confirm' => $reloadMessage,
@ -52,12 +52,12 @@ return function (App\Event\BuildStationMenu $e) {
'profile' => [
'label' => __('Profile'),
'icon' => 'image',
'url' => (string)$router->fromHere('stations:profile:index'),
'url' => $router->fromHere('stations:profile:index'),
],
'public' => [
'label' => __('Public Page'),
'icon' => 'public',
'url' => (string)$router->named('public:index', ['station_id' => $station->getShortName()]),
'url' => $router->named('public:index', ['station_id' => $station->getShortName()]),
'external' => true,
'visible' => $station->getEnablePublicPage(),
],
@ -69,46 +69,46 @@ return function (App\Event\BuildStationMenu $e) {
'files' => [
'label' => __('Music Files'),
'icon' => 'library_music',
'url' => (string)$router->fromHere('stations:files:index'),
'url' => $router->fromHere('stations:files:index'),
'permission' => StationPermissions::Media,
],
'reports_duplicates' => [
'label' => __('Duplicate Songs'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:files:index') . '#special:duplicates',
'url' => $router->fromHere('stations:files:index') . '#special:duplicates',
'permission' => StationPermissions::Media,
],
'reports_unprocessable' => [
'label' => __('Unprocessable Files'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:files:index') . '#special:unprocessable',
'url' => $router->fromHere('stations:files:index') . '#special:unprocessable',
'permission' => StationPermissions::Media,
],
'reports_unassigned' => [
'label' => __('Unassigned Files'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:files:index') . '#special:unassigned',
'url' => $router->fromHere('stations:files:index') . '#special:unassigned',
'permission' => StationPermissions::Media,
],
'ondemand' => [
'label' => __('On-Demand Media'),
'class' => 'text-muted',
'icon' => 'cloud_download',
'url' => (string)$router->named('public:ondemand', ['station_id' => $station->getShortName()]),
'url' => $router->named('public:ondemand', ['station_id' => $station->getShortName()]),
'external' => true,
'visible' => $station->getEnableOnDemand(),
],
'sftp_users' => [
'label' => __('SFTP Users'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:sftp_users:index'),
'url' => $router->fromHere('stations:sftp_users:index'),
'visible' => StationFeatures::Sftp->supportedForStation($station),
'permission' => StationPermissions::Media,
],
'bulk_media' => [
'label' => __('Bulk Media Import/Export'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:bulk-media'),
'url' => $router->fromHere('stations:bulk-media'),
'permission' => StationPermissions::Media,
],
],
@ -117,7 +117,7 @@ return function (App\Event\BuildStationMenu $e) {
'playlists' => [
'label' => __('Playlists'),
'icon' => 'queue_music',
'url' => (string)$router->fromHere('stations:playlists:index'),
'url' => $router->fromHere('stations:playlists:index'),
'visible' => StationFeatures::Media->supportedForStation($station),
'permission' => StationPermissions::Media,
],
@ -125,7 +125,7 @@ return function (App\Event\BuildStationMenu $e) {
'podcasts' => [
'label' => __('Podcasts'),
'icon' => 'cast',
'url' => (string)$router->fromHere('stations:podcasts:index'),
'url' => $router->fromHere('stations:podcasts:index'),
'visible' => StationFeatures::Podcasts->supportedForStation($station),
'permission' => StationPermissions::Podcasts,
],
@ -138,20 +138,21 @@ return function (App\Event\BuildStationMenu $e) {
'streamers' => [
'label' => __('Streamer/DJ Accounts'),
'icon' => 'mic',
'url' => (string)$router->fromHere('stations:streamers:index'),
'url' => $router->fromHere('stations:streamers:index'),
'permission' => StationPermissions::Streamers,
],
'web_dj' => [
'label' => __('Web DJ'),
'icon' => 'surround_sound',
'url' => (string)$router->named(
'url' => (string)(
$router->namedAsUri(
'public:dj',
['station_id' => $station->getShortName()],
[],
true
)
->withScheme('https'),
)->withScheme('https')
),
'visible' => $station->getEnablePublicPage(),
'external' => true,
],
@ -161,7 +162,7 @@ return function (App\Event\BuildStationMenu $e) {
'webhooks' => [
'label' => __('Web Hooks'),
'icon' => 'code',
'url' => (string)$router->fromHere('stations:webhooks:index'),
'url' => $router->fromHere('stations:webhooks:index'),
'visible' => StationFeatures::Webhooks->supportedForStation($station),
'permission' => StationPermissions::WebHooks,
],
@ -173,24 +174,24 @@ return function (App\Event\BuildStationMenu $e) {
'items' => [
'reports_overview' => [
'label' => __('Station Statistics'),
'url' => (string)$router->fromHere('stations:reports:overview'),
'url' => $router->fromHere('stations:reports:overview'),
],
'reports_listeners' => [
'label' => __('Listeners'),
'url' => (string)$router->fromHere('stations:reports:listeners'),
'url' => $router->fromHere('stations:reports:listeners'),
],
'reports_requests' => [
'label' => __('Song Requests'),
'url' => (string)$router->fromHere('stations:reports:requests'),
'url' => $router->fromHere('stations:reports:requests'),
'visible' => $station->getEnableRequests(),
],
'reports_timeline' => [
'label' => __('Song Playback Timeline'),
'url' => (string)$router->fromHere('stations:reports:timeline'),
'url' => $router->fromHere('stations:reports:timeline'),
],
'reports_soundexchange' => [
'label' => __('SoundExchange Royalties'),
'url' => (string)$router->fromHere('stations:reports:soundexchange'),
'url' => $router->fromHere('stations:reports:soundexchange'),
],
],
],
@ -202,41 +203,41 @@ return function (App\Event\BuildStationMenu $e) {
'mounts' => [
'label' => __('Mount Points'),
'icon' => 'wifi_tethering',
'url' => (string)$router->fromHere('stations:mounts:index'),
'url' => $router->fromHere('stations:mounts:index'),
'visible' => StationFeatures::MountPoints->supportedForStation($station),
'permission' => StationPermissions::MountPoints,
],
'hls_streams' => [
'label' => __('HLS Streams'),
'url' => (string)$router->fromHere('stations:hls_streams:index'),
'url' => $router->fromHere('stations:hls_streams:index'),
'visible' => StationFeatures::HlsStreams->supportedForStation($station),
'permission' => StationPermissions::MountPoints,
],
'remotes' => [
'label' => __('Remote Relays'),
'icon' => 'router',
'url' => (string)$router->fromHere('stations:remotes:index'),
'url' => $router->fromHere('stations:remotes:index'),
'visible' => StationFeatures::RemoteRelays->supportedForStation($station),
'permission' => StationPermissions::RemoteRelays,
],
'fallback' => [
'label' => __('Custom Fallback File'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:fallback'),
'url' => $router->fromHere('stations:fallback'),
'visible' => StationFeatures::Media->supportedForStation($station),
'permission' => StationPermissions::Broadcasting,
],
'ls_config' => [
'label' => __('Edit Liquidsoap Configuration'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:util:ls_config'),
'url' => $router->fromHere('stations:util:ls_config'),
'visible' => StationFeatures::CustomLiquidsoapConfig->supportedForStation($station),
'permission' => StationPermissions::Broadcasting,
],
'stations:stereo_tool_config' => [
'label' => __('Upload Stereo Tool Configuration'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:stereo_tool_config'),
'url' => $router->fromHere('stations:stereo_tool_config'),
'visible' => $settings->getEnableAdvancedFeatures()
&& StationFeatures::Media->supportedForStation($station)
&& AudioProcessingMethods::StereoTool === $backendConfig->getAudioProcessingMethodEnum(),
@ -245,14 +246,14 @@ return function (App\Event\BuildStationMenu $e) {
'queue' => [
'label' => __('Upcoming Song Queue'),
'class' => 'text-muted',
'url' => (string)$router->fromHere('stations:queue:index'),
'url' => $router->fromHere('stations:queue:index'),
'permission' => StationPermissions::Broadcasting,
'visible' => $station->supportsAutoDjQueue(),
],
'reload' => [
'label' => __('Reload Configuration'),
'class' => 'text-muted api-call',
'url' => (string)$router->fromHere('api:stations:reload'),
'url' => $router->fromHere('api:stations:reload'),
'confirm' => $willNotDisconnectMessage,
'permission' => StationPermissions::Broadcasting,
'visible' => $hasLocalServices && $reloadSupported,
@ -260,7 +261,7 @@ return function (App\Event\BuildStationMenu $e) {
'restart' => [
'label' => __('Restart Broadcasting'),
'class' => 'text-muted api-call',
'url' => (string)$router->fromHere('api:stations:restart'),
'url' => $router->fromHere('api:stations:restart'),
'confirm' => $willDisconnectMessage,
'permission' => StationPermissions::Broadcasting,
'visible' => $hasLocalServices,
@ -271,7 +272,7 @@ return function (App\Event\BuildStationMenu $e) {
'logs' => [
'label' => __('Logs'),
'icon' => 'web_stories',
'url' => (string)$router->fromHere('stations:logs'),
'url' => $router->fromHere('stations:logs'),
'permission' => StationPermissions::Logs,
],
]

View File

@ -78,7 +78,7 @@ return static function (RouteCollectorProxy $group) {
'/relays',
function (ServerRequest $request, Response $response) {
return $response->withRedirect(
(string)$request->getRouter()->fromHere('api:internal:relays')
$request->getRouter()->fromHere('api:internal:relays')
);
}
);

View File

@ -16,7 +16,7 @@ return static function (RouteCollectorProxy $app) {
'',
function (ServerRequest $request, Response $response, ...$params) {
return $response->withRedirect(
(string)$request->getRouter()->fromHere('stations:profile:index')
$request->getRouter()->fromHere('stations:profile:index')
);
}
)->setName('stations:index:index');

View File

@ -22,7 +22,7 @@ final class ApiKeysAction
id: 'admin-api-keys',
title: __('API Keys'),
props: [
'apiUrl' => (string)$router->named('api:admin:api-keys'),
'apiUrl' => $router->named('api:admin:api-keys'),
],
);
}

View File

@ -22,7 +22,7 @@ final class AuditLogAction
id: 'admin-audit-log',
title: __('Audit Log'),
props: [
'baseApiUrl' => (string)$router->fromHere('api:admin:auditlog'),
'baseApiUrl' => $router->fromHere('api:admin:auditlog'),
]
);
}

View File

@ -30,9 +30,9 @@ final class BackupsAction
id: 'admin-backups',
title: __('Backups'),
props: [
'listUrl' => (string)$router->named('api:admin:backups'),
'runBackupUrl' => (string)$router->named('api:admin:backups:run'),
'settingsUrl' => (string)$router->named('api:admin:settings', [
'listUrl' => $router->named('api:admin:backups'),
'runBackupUrl' => $router->named('api:admin:backups:run'),
'settingsUrl' => $router->named('api:admin:settings', [
'group' => Entity\Settings::GROUP_BACKUP,
]),
'isDocker' => $this->environment->isDocker(),

View File

@ -24,16 +24,16 @@ final class BrandingAction
id: 'admin-branding',
title: __('Custom Branding'),
props: [
'settingsApiUrl' => (string)$router->named('api:admin:settings', [
'settingsApiUrl' => $router->named('api:admin:settings', [
'group' => Settings::GROUP_BRANDING,
]),
'browserIconApiUrl' => (string)$router->named('api:admin:custom_assets', [
'browserIconApiUrl' => $router->named('api:admin:custom_assets', [
'type' => AssetTypes::BrowserIcon->value,
]),
'backgroundApiUrl' => (string)$router->named('api:admin:custom_assets', [
'backgroundApiUrl' => $router->named('api:admin:custom_assets', [
'type' => AssetTypes::Background->value,
]),
'albumArtApiUrl' => (string)$router->named('api:admin:custom_assets', [
'albumArtApiUrl' => $router->named('api:admin:custom_assets', [
'type' => AssetTypes::AlbumArt->value,
]),
],

View File

@ -23,7 +23,7 @@ final class CustomFieldsAction
id: 'admin-custom-fields',
title: __('Custom Fields'),
props: [
'listUrl' => (string)$router->fromHere('api:admin:custom_fields'),
'listUrl' => $router->fromHere('api:admin:custom_fields'),
'autoAssignTypes' => MetadataTags::getNames(),
]
);

View File

@ -28,6 +28,6 @@ final class ClearCacheAction
// Flash an update to ensure the session is recreated.
$request->getFlash()->addMessage($resultOutput, Flash::SUCCESS);
return $response->withRedirect((string)$request->getRouter()->fromHere('admin:debug:index'));
return $response->withRedirect($request->getRouter()->fromHere('admin:debug:index'));
}
}

View File

@ -32,6 +32,6 @@ final class ClearQueueAction
// Flash an update to ensure the session is recreated.
$request->getFlash()->addMessage($resultOutput, Flash::SUCCESS);
return $response->withRedirect((string)$request->getRouter()->fromHere('admin:debug:index'));
return $response->withRedirect($request->getRouter()->fromHere('admin:debug:index'));
}
}

View File

@ -22,7 +22,7 @@ final class GeoLiteAction
id: 'admin-geolite',
title: __('Install GeoLite IP Database'),
props: [
'apiUrl' => (string)$router->named('api:admin:geolite'),
'apiUrl' => $router->named('api:admin:geolite'),
],
);
}

View File

@ -30,8 +30,8 @@ final class IndexAction
title: __('Administration'),
props: [
'adminPanels' => $viewData['admin_panels'] ?? [],
'statsUrl' => (string)$router->named('api:admin:server:stats'),
'servicesUrl' => (string)$router->named('api:admin:services'),
'statsUrl' => $router->named('api:admin:server:stats'),
'servicesUrl' => $router->named('api:admin:services'),
]
);
}

View File

@ -30,7 +30,7 @@ final class LogsAction
$stationLogs[] = [
'id' => $station->getIdRequired(),
'name' => $station->getName(),
'url' => (string)$router->named('api:stations:logs', [
'url' => $router->named('api:stations:logs', [
'station_id' => $station->getIdRequired(),
]),
];
@ -43,7 +43,7 @@ final class LogsAction
id: 'admin-logs',
title: __('System Logs'),
props: [
'systemLogsUrl' => (string)$router->fromHere('api:admin:logs'),
'systemLogsUrl' => $router->fromHere('api:admin:logs'),
'stationLogs' => $stationLogs,
],
);

View File

@ -30,7 +30,7 @@ final class PermissionsAction
id: 'admin-permissions',
title: __('Roles & Permissions'),
props: [
'listUrl' => (string)$router->fromHere('api:admin:roles'),
'listUrl' => $router->fromHere('api:admin:roles'),
'stations' => $this->stationRepo->fetchSelect(),
'globalPermissions' => $actions['global'],
'stationPermissions' => $actions['station'],

View File

@ -29,11 +29,11 @@ final class SettingsAction
id: 'admin-settings',
title: __('System Settings'),
props: [
'apiUrl' => (string)$router->named('api:admin:settings', [
'apiUrl' => $router->named('api:admin:settings', [
'group' => Settings::GROUP_GENERAL,
]),
'testMessageUrl' => (string)$router->named('api:admin:send-test-message'),
'acmeUrl' => (string)$router->named('api:admin:acme'),
'testMessageUrl' => $router->named('api:admin:send-test-message'),
'acmeUrl' => $router->named('api:admin:acme'),
'releaseChannel' => $this->version->getReleaseChannelEnum()->value,
],
);

View File

@ -27,7 +27,7 @@ final class ShoutcastAction
id: 'admin-shoutcast',
title: __('Install Shoutcast 2 DNAS'),
props: [
'apiUrl' => (string)$router->named('api:admin:shoutcast'),
'apiUrl' => $router->named('api:admin:shoutcast'),
],
);
}

View File

@ -32,7 +32,7 @@ final class StationsAction
props: array_merge(
$this->stationFormComponent->getProps($request),
[
'listUrl' => (string)$router->fromHere('api:admin:stations'),
'listUrl' => $router->fromHere('api:admin:stations'),
'frontendTypes' => $this->adapters->listFrontendAdapters(),
'backendTypes' => $this->adapters->listBackendAdapters(),
]

View File

@ -22,7 +22,7 @@ final class StereoToolAction
id: 'admin-stereo-tool',
title: __('Install Stereo Tool'),
props: [
'apiUrl' => (string)$router->named('api:admin:stereo_tool'),
'apiUrl' => $router->named('api:admin:stereo_tool'),
],
);
}

View File

@ -22,7 +22,7 @@ final class StorageLocationsAction
id: 'admin-storage-locations',
title: __('Storage Locations'),
props: [
'listUrl' => (string)$router->fromHere('api:admin:storage_locations'),
'listUrl' => $router->fromHere('api:admin:storage_locations'),
],
);
}

View File

@ -28,7 +28,7 @@ final class UsersAction
id: 'admin-users',
title: __('Users'),
props: [
'listUrl' => (string)$router->fromHere('api:admin:users'),
'listUrl' => $router->fromHere('api:admin:users'),
'roles' => $this->roleRepo->fetchSelect(),
]
);

View File

@ -69,7 +69,7 @@ abstract class AbstractApiCrudController
if ($record instanceof IdentifiableEntityInterface) {
$return['links'] = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal

View File

@ -34,7 +34,7 @@ final class GenerateCertificateAction
[
'success' => true,
'links' => [
'log' => (string)$router->fromHere('api:admin:acme-log', [
'log' => $router->fromHere('api:admin:acme-log', [
'path' => basename($tempFile),
]),
],

View File

@ -61,11 +61,11 @@ final class GetAction
$paginator = Paginator::fromArray($backups, $request);
$paginator->setPostprocessor(function ($row) use ($router) {
$row['links'] = [
'download' => (string)$router->fromHere(
'download' => $router->fromHere(
'api:admin:backups:download',
['path' => $row['pathEncoded']]
),
'delete' => (string)$router->fromHere(
'delete' => $router->fromHere(
'api:admin:backups:delete',
['path' => $row['pathEncoded']]
),

View File

@ -46,7 +46,7 @@ final class RunAction
'excludeMedia' => $message->excludeMedia,
'outputPath' => $message->outputPath,
'links' => [
'log' => (string)$router->named(
'log' => $router->named(
'api:admin:backups:log',
['path' => basename($tempFile)]
),

View File

@ -35,7 +35,7 @@ final class LogsAction
function (string $key, array $row) use ($router) {
$row['key'] = $key;
$row['links'] = [
'self' => (string)$router->named(
'self' => $router->named(
'api:admin:log',
[
'log' => $key,

View File

@ -33,7 +33,7 @@ final class ServiceControlController
$row['links'] = [];
if ($canRestart) {
$row['links']['restart'] = (string)$router->fromHere(
$row['links']['restart'] = $router->fromHere(
'api:admin:services:restart',
['service' => $service->name]
);

View File

@ -192,17 +192,17 @@ class StationsController extends AbstractAdminApiCrudController
$router = $request->getRouter();
$return['links'] = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal
),
'manage' => (string)$router->named(
'manage' => $router->named(
routeName: 'stations:index:index',
routeParams: ['station_id' => $record->getIdRequired()],
absolute: !$isInternal
),
'clone' => (string)$router->fromHere(
'clone' => $router->fromHere(
routeName: 'api:admin:station:clone',
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal

View File

@ -177,12 +177,12 @@ class UsersController extends AbstractAdminApiCrudController
$return['is_me'] = $currentUser->getIdRequired() === $record->getIdRequired();
$return['links'] = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal
),
'masquerade' => (string)$router->fromHere(
'masquerade' => $router->fromHere(
routeName: 'account:masquerade',
routeParams: [
'id' => $record->getIdRequired(),

View File

@ -49,12 +49,12 @@ final class StationsAction
$row->fromParentObject($np);
$row->links = [
'public' => (string)$router->named('public:index', ['station_id' => $station->getShortName()]),
'manage' => (string)$router->named('stations:index:index', ['station_id' => $station->getId()]),
'public' => $router->named('public:index', ['station_id' => $station->getShortName()]),
'manage' => $router->named('stations:index:index', ['station_id' => $station->getId()]),
];
if ($listenersEnabled && $acl->isAllowed(StationPermissions::Reports, $station->getId())) {
$row->links['listeners'] = (string)$router->named(
$row->links['listeners'] = $router->named(
'stations:reports:listeners',
['station_id' => $station->getId()]
);

View File

@ -23,7 +23,7 @@ final class OpenApiAction
$apiBaseUrl = str_replace(
'/openapi.yml',
'',
(string)$request->getRouter()->fromHere(absolute: true)
$request->getRouter()->fromHere(absolute: true)
);
$yaml = $this->apiDocsCommand->generate(true, $apiBaseUrl)?->toYaml();

View File

@ -406,7 +406,7 @@ final class ListAction
$artMediaId .= '-' . $row->media->art_updated_at;
}
$row->media->art = (string)$router->named(
$row->media->art = $router->named(
'api:stations:media:art',
[
'station_id' => $stationId,
@ -415,21 +415,21 @@ final class ListAction
);
$row->media->links = [
'play' => (string)$router->named(
'play' => $router->named(
'api:stations:files:play',
['station_id' => $stationId, 'id' => $row->media->media_id],
[],
true
),
'edit' => (string)$router->named(
'edit' => $router->named(
'api:stations:file',
['station_id' => $stationId, 'id' => $row->media->media_id],
),
'art' => (string)$router->named(
'art' => $router->named(
'api:stations:media:art-internal',
['station_id' => $stationId, 'media_id' => $row->media->media_id]
),
'waveform' => (string)$router->named(
'waveform' => $router->named(
'api:stations:media:waveform',
[
'station_id' => $stationId,
@ -440,12 +440,12 @@ final class ListAction
}
$row->links = [
'download' => (string)$router->named(
'download' => $router->named(
'api:stations:files:download',
['station_id' => $stationId],
['file' => $row->path]
),
'rename' => (string)$router->named(
'rename' => $router->named(
'api:stations:files:rename',
['station_id' => $stationId],
['file' => $row->path]

View File

@ -35,7 +35,7 @@ final class LogsAction
function (string $key, array $row) use ($router, $station_id) {
$row['key'] = $key;
$row['links'] = [
'self' => (string)$router->named(
'self' => $router->named(
'api:stations:log',
[
'station_id' => $station_id,

View File

@ -200,7 +200,7 @@ final class MountsController extends AbstractStationApiCrudController
$frontend = $this->adapters->getFrontendAdapter($station);
$return['links']['intro'] = (string)$router->fromHere(
$return['links']['intro'] = $router->fromHere(
routeName: 'api:stations:mounts:intro',
routeParams: ['id' => $record->getId()],
absolute: true

View File

@ -135,7 +135,7 @@ final class ListAction
station: $station
);
$row->playlist = $playlist['name'];
$row->download_url = (string)$router->named(
$row->download_url = $router->named(
'api:stations:ondemand:download',
[
'station_id' => $station->getId(),

View File

@ -54,7 +54,7 @@ final class GetOrderAction
array_map(
static function (array $row) use ($router, $station): array {
$row['media']['links'] = [
'play' => (string)$router->named(
'play' => $router->named(
'api:stations:files:play',
['station_id' => $station->getIdRequired(), 'id' => $row['media']['unique_id']],
[],

View File

@ -220,7 +220,7 @@ final class PlaylistsController extends AbstractScheduledEntityController
'title' => $playlist->getName(),
'start' => $start->toIso8601String(),
'end' => $end->toIso8601String(),
'edit_url' => (string)$request->getRouter()->named(
'edit_url' => $request->getRouter()->named(
'api:stations:playlist',
['station_id' => $station->getId(), 'id' => $playlist->getId()]
),
@ -257,39 +257,39 @@ final class PlaylistsController extends AbstractScheduledEntityController
$router = $request->getRouter();
$return['links'] = [
'toggle' => (string)$router->fromHere(
'toggle' => $router->fromHere(
'api:stations:playlist:toggle',
['id' => $record->getId()],
[],
!$isInternal
),
'order' => (string)$router->fromHere(
'order' => $router->fromHere(
'api:stations:playlist:order',
['id' => $record->getId()],
[],
!$isInternal
),
'reshuffle' => (string)$router->fromHere(
'reshuffle' => $router->fromHere(
routeName: 'api:stations:playlist:reshuffle',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal
),
'queue' => (string)$router->fromHere(
'queue' => $router->fromHere(
routeName: 'api:stations:playlist:queue',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal
),
'import' => (string)$router->fromHere(
'import' => $router->fromHere(
routeName: 'api:stations:playlist:import',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal
),
'clone' => (string)$router->fromHere(
'clone' => $router->fromHere(
routeName: 'api:stations:playlist:clone',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal
),
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
$this->resourceRouteName,
['id' => $record->getId()],
[],
@ -298,7 +298,7 @@ final class PlaylistsController extends AbstractScheduledEntityController
];
foreach (['pls', 'm3u'] as $format) {
$return['links']['export'][$format] = (string)$router->fromHere(
$return['links']['export'][$format] = $router->fromHere(
routeName: 'api:stations:playlist:export',
routeParams: ['id' => $record->getId(), 'format' => $format],
absolute: !$isInternal

View File

@ -376,24 +376,24 @@ final class PodcastEpisodesController extends AbstractApiCrudController
$return->art_updated_at = $record->getArtUpdatedAt();
$return->has_custom_art = (0 !== $return->art_updated_at);
$return->art = (string)$router->fromHere(
$return->art = $router->fromHere(
routeName: 'api:stations:podcast:episode:art',
routeParams: ['episode_id' => $record->getId() . '|' . $record->getArtUpdatedAt()],
absolute: true
);
$return->links = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['episode_id' => $record->getId()],
absolute: !$isInternal
),
'public' => (string)$router->fromHere(
'public' => $router->fromHere(
routeName: 'public:podcast:episode',
routeParams: ['episode_id' => $record->getId()],
absolute: !$isInternal
),
'download' => (string)$router->fromHere(
'download' => $router->fromHere(
routeName: 'api:stations:podcast:episode:download',
routeParams: ['episode_id' => $record->getId()],
absolute: !$isInternal
@ -404,12 +404,12 @@ final class PodcastEpisodesController extends AbstractApiCrudController
$station = $request->getStation();
if ($acl->isAllowed(StationPermissions::Podcasts, $station)) {
$return->links['art'] = (string)$router->fromHere(
$return->links['art'] = $router->fromHere(
routeName: 'api:stations:podcast:episode:art-internal',
routeParams: ['episode_id' => $record->getId()],
absolute: !$isInternal
);
$return->links['media'] = (string)$router->fromHere(
$return->links['media'] = $router->fromHere(
routeName: 'api:stations:podcast:episode:media-internal',
routeParams: ['episode_id' => $record->getId()],
absolute: !$isInternal

View File

@ -312,29 +312,29 @@ final class PodcastsController extends AbstractApiCrudController
$return->episodes = $episodes;
$return->has_custom_art = (0 !== $record->getArtUpdatedAt());
$return->art = (string)$router->fromHere(
$return->art = $router->fromHere(
routeName: 'api:stations:podcast:art',
routeParams: ['podcast_id' => $record->getId() . '|' . $record->getArtUpdatedAt()],
absolute: true
);
$return->links = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
),
'episodes' => (string)$router->fromHere(
'episodes' => $router->fromHere(
routeName: 'api:stations:podcast:episodes',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
),
'public_episodes' => (string)$router->fromHere(
'public_episodes' => $router->fromHere(
routeName: 'public:podcast:episodes',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
),
'public_feed' => (string)$router->fromHere(
'public_feed' => $router->fromHere(
routeName: 'public:podcast:feed',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
@ -344,18 +344,18 @@ final class PodcastsController extends AbstractApiCrudController
$acl = $request->getAcl();
if ($acl->isAllowed(StationPermissions::Podcasts, $station)) {
$return->links['art'] = (string)$router->fromHere(
$return->links['art'] = $router->fromHere(
routeName: 'api:stations:podcast:art-internal',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
);
$return->links['episode_new_art'] = (string)$router->fromHere(
$return->links['episode_new_art'] = $router->fromHere(
routeName: 'api:stations:podcast:episodes:new-art',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal
);
$return->links['episode_new_media'] = (string)$router->fromHere(
$return->links['episode_new_media'] = $router->fromHere(
routeName: 'api:stations:podcast:episodes:new-media',
routeParams: ['podcast_id' => $record->getId()],
absolute: !$isInternal

View File

@ -150,7 +150,12 @@ final class QueueController extends AbstractStationApiCrudController
$apiResponse->log = $this->queue->getQueueRowLog($record);
$apiResponse->links = [
'self' => (string)$router->fromHere($this->resourceRouteName, ['id' => $record->getId()], [], !$isInternal),
'self' => $router->fromHere(
$this->resourceRouteName,
['id' => $record->getId()],
[],
!$isInternal
),
];
return $apiResponse;

View File

@ -197,7 +197,7 @@ final class RemotesController extends AbstractStationApiCrudController
$return->is_editable = $record->isEditable();
$return->links = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal

View File

@ -51,7 +51,7 @@ final class RequestsController
$row['links'] = [];
if (0 === $row['played_at']) {
$row['links']['delete'] = (string)$router->fromHere(
$row['links']['delete'] = $router->fromHere(
'api:stations:reports:requests:delete',
['request_id' => $row['id']]
);

View File

@ -124,7 +124,7 @@ final class RequestsController
$row = new Entity\Api\StationRequest();
$row->song = ($this->songApiGenerator)($media_row, $station, $baseUrl);
$row->request_id = $media_row->getUniqueId();
$row->request_url = (string)$router->named(
$row->request_url = $router->named(
'api:requests:submit',
[
'station_id' => $station->getId(),

View File

@ -91,13 +91,13 @@ final class BroadcastsController extends AbstractApiCrudController
'path' => $recordingPath,
'size' => $fsRecordings->fileSize($recordingPath),
'links' => [
'download' => (string)$router->fromHere(
'download' => $router->fromHere(
'api:stations:streamer:broadcast:download',
$routeParams,
[],
true
),
'delete' => (string)$router->fromHere(
'delete' => $router->fromHere(
'api:stations:streamer:broadcast:delete',
$routeParams,
[],

View File

@ -260,7 +260,7 @@ final class StreamersController extends AbstractScheduledEntityController
'title' => $streamer->getDisplayName(),
'start' => $start->toIso8601String(),
'end' => $end->toIso8601String(),
'edit_url' => (string)$request->getRouter()->named(
'edit_url' => $request->getRouter()->named(
'api:stations:streamer',
['station_id' => $station->getId(), 'id' => $streamer->getId()]
),
@ -283,18 +283,18 @@ final class StreamersController extends AbstractScheduledEntityController
$isInternal = ('true' === $request->getParam('internal', 'false'));
$return['has_custom_art'] = (0 !== $record->getArtUpdatedAt());
$return['art'] = (string)$router->fromHere(
$return['art'] = $router->fromHere(
routeName: 'api:stations:streamer:art',
routeParams: ['id' => $record->getIdRequired() . '|' . $record->getArtUpdatedAt()],
absolute: !$isInternal
);
$return['links']['broadcasts'] = (string)$router->fromHere(
$return['links']['broadcasts'] = $router->fromHere(
routeName: 'api:stations:streamer:broadcasts',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal
);
$return['links']['art'] = (string)$router->fromHere(
$return['links']['art'] = $router->fromHere(
routeName: 'api:stations:streamer:art-internal',
routeParams: ['id' => $record->getId()],
absolute: !$isInternal

View File

@ -42,7 +42,7 @@ final class TestAction
[
'success' => true,
'links' => [
'log' => (string)$router->fromHere('api:stations:webhook:test-log', [
'log' => $router->fromHere('api:stations:webhook:test-log', [
'path' => basename($tempFile),
]),
],

View File

@ -192,17 +192,17 @@ final class WebhooksController extends AbstractStationApiCrudController
$router = $request->getRouter();
$return['links'] = [
'self' => (string)$router->fromHere(
'self' => $router->fromHere(
routeName: $this->resourceRouteName,
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal
),
'toggle' => (string)$router->fromHere(
'toggle' => $router->fromHere(
routeName: 'api:stations:webhook:toggle',
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal
),
'test' => (string)$router->fromHere(
'test' => $router->fromHere(
routeName: 'api:stations:webhook:test',
routeParams: ['id' => $record->getIdRequired()],
absolute: !$isInternal

View File

@ -17,6 +17,6 @@ final class EndMasqueradeAction
$auth = $request->getAuth();
$auth->endMasquerade();
return $response->withRedirect((string)$request->getRouter()->named('admin:users:index'));
return $response->withRedirect($request->getRouter()->named('admin:users:index'));
}
}

View File

@ -87,7 +87,7 @@ final class ForgotPasswordAction
Flash::SUCCESS
);
return $response->withRedirect((string)$request->getRouter()->named('account:login'));
return $response->withRedirect($request->getRouter()->named('account:login'));
}
return $view->renderToResponse($response, 'frontend/account/forgot');

View File

@ -41,12 +41,12 @@ final class LoginAction
)->getSingleScalarResult();
if (0 === $num_users) {
return $response->withRedirect((string)$request->getRouter()->named('setup:index'));
return $response->withRedirect($request->getRouter()->named('setup:index'));
}
}
if ($auth->isLoggedIn()) {
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
}
$flash = $request->getFlash();
@ -88,7 +88,7 @@ final class LoginAction
// Redirect for 2FA.
if (!$auth->isLoginComplete()) {
return $response->withRedirect((string)$request->getRouter()->named('account:login:2fa'));
return $response->withRedirect($request->getRouter()->named('account:login:2fa'));
}
// Redirect to complete setup if it's not completed yet.
@ -101,7 +101,7 @@ final class LoginAction
),
Flash::SUCCESS
);
return $response->withRedirect((string)$request->getRouter()->named('setup:index'));
return $response->withRedirect($request->getRouter()->named('setup:index'));
}
$flash->addMessage(
@ -111,7 +111,7 @@ final class LoginAction
$referrer = $session->get('login_referrer');
return $response->withRedirect(
(!empty($referrer)) ? $referrer : (string)$request->getRouter()->named('dashboard')
(!empty($referrer)) ? $referrer : $request->getRouter()->named('dashboard')
);
}

View File

@ -17,6 +17,6 @@ final class LogoutAction
$auth = $request->getAuth();
$auth->logout();
return $response->withRedirect((string)$request->getRouter()->named('account:login'));
return $response->withRedirect($request->getRouter()->named('account:login'));
}
}

View File

@ -42,6 +42,6 @@ final class MasqueradeAction
Flash::SUCCESS
);
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
}
}

View File

@ -38,7 +38,7 @@ final class RecoverAction
Flash::ERROR
);
return $response->withRedirect((string)$request->getRouter()->named('account:login'));
return $response->withRedirect($request->getRouter()->named('account:login'));
}
$csrf = $request->getCsrf();
@ -73,7 +73,7 @@ final class RecoverAction
Flash::SUCCESS
);
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
} catch (Throwable $e) {
$error = $e->getMessage();
}

View File

@ -36,7 +36,7 @@ final class TwoFactorAction
return $response->withRedirect($referrer);
}
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
}
$flash->addMessage(

View File

@ -35,15 +35,15 @@ final class DashboardAction
id: 'dashboard',
title: __('Dashboard'),
props: [
'userUrl' => (string)$router->named('api:frontend:account:me'),
'profileUrl' => (string)$router->named('profile:index'),
'adminUrl' => (string)$router->named('admin:index:index'),
'userUrl' => $router->named('api:frontend:account:me'),
'profileUrl' => $router->named('profile:index'),
'adminUrl' => $router->named('admin:index:index'),
'showAdmin' => $acl->isAllowed(GlobalPermissions::View),
'notificationsUrl' => (string)$router->named('api:frontend:dashboard:notifications'),
'notificationsUrl' => $router->named('api:frontend:dashboard:notifications'),
'showCharts' => $showCharts,
'chartsUrl' => (string)$router->named('api:frontend:dashboard:charts'),
'manageStationsUrl' => (string)$router->named('admin:stations:index'),
'stationsUrl' => (string)$router->named('api:frontend:dashboard:stations'),
'chartsUrl' => $router->named('api:frontend:dashboard:charts'),
'manageStationsUrl' => $router->named('admin:stations:index'),
'stationsUrl' => $router->named('api:frontend:dashboard:stations'),
'showAlbumArt' => !$settings->getHideAlbumArt(),
]
);

View File

@ -23,7 +23,7 @@ final class IndexAction
// Redirect to complete setup, if it hasn't been completed yet.
$settings = $this->settingsRepo->readSettings();
if (!$settings->isSetupComplete()) {
return $response->withRedirect((string)$request->getRouter()->named('setup:index'));
return $response->withRedirect($request->getRouter()->named('setup:index'));
}
// Redirect to login screen if the user isn't logged in.
@ -36,10 +36,10 @@ final class IndexAction
return $response->withRedirect((string)$homepageRedirect, 302);
}
return $response->withRedirect((string)$request->getRouter()->named('account:login'));
return $response->withRedirect($request->getRouter()->named('account:login'));
}
// Redirect to dashboard if no other custom redirection rules exist.
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
}
}

View File

@ -28,10 +28,10 @@ final class IndexAction
id: 'account',
title: __('My Account'),
props: [
'userUrl' => (string)$router->named('api:frontend:account:me'),
'changePasswordUrl' => (string)$router->named('api:frontend:account:password'),
'twoFactorUrl' => (string)$router->named('api:frontend:account:two-factor'),
'apiKeysApiUrl' => (string)$router->named('api:frontend:api-keys'),
'userUrl' => $router->named('api:frontend:account:me'),
'changePasswordUrl' => $router->named('api:frontend:account:password'),
'twoFactorUrl' => $router->named('api:frontend:account:two-factor'),
'apiKeysApiUrl' => $router->named('api:frontend:api-keys'),
'supportedLocales' => $supportedLocales,
]
);

View File

@ -35,7 +35,7 @@ final class ThemeAction
$referrer = $request->getHeaderLine('Referer');
return $response->withRedirect(
$referrer ?: (string)$request->getRouter()->named('dashboard')
$referrer ?: $request->getRouter()->named('dashboard')
);
}
}

View File

@ -52,7 +52,7 @@ final class HistoryAction
'useNchan' => $useNChan,
'nowPlayingUri' => $useNChan
? '/api/live/nowplaying/' . urlencode($station->getShortName())
: (string)$router->named('api:nowplaying:index', ['station_id' => $station->getId()]),
: $router->named('api:nowplaying:index', ['station_id' => $station->getId()]),
],
);
}

View File

@ -69,7 +69,7 @@ final class OnDemandAction
'hide_footer' => true,
],
props: [
'listUrl' => (string)$router->fromHere('api:stations:ondemand:list'),
'listUrl' => $router->fromHere('api:stations:ondemand:list'),
'showDownloadButton' => $station->getEnableOnDemandDownload(),
'customFields' => $customFields,
'stationName' => $station->getName(),

View File

@ -63,7 +63,7 @@ final class PlayerAction
$props['nowPlayingUri'] = '/api/live/nowplaying/' . urlencode($station->getShortName());
} else {
$props['useNchan'] = false;
$props['nowPlayingUri'] = (string)$router->named(
$props['nowPlayingUri'] = $router->named(
'api:nowplaying:index',
['station_id' => $station->getId()]
);
@ -92,11 +92,11 @@ final class PlayerAction
// Render full page player.
$props['stationName'] = $station->getName();
$props['enableRequests'] = $station->getEnableRequests();
$props['downloadPlaylistUri'] = (string)$router->named(
$props['downloadPlaylistUri'] = $router->named(
'public:playlist',
['station_id' => $station->getShortName(), 'format' => 'pls']
);
$props['requestListUri'] = (string)$router->named(
$props['requestListUri'] = $router->named(
'api:requests:list',
['station_id' => $station->getId()]
);

View File

@ -44,7 +44,7 @@ final class PodcastEpisodeAction
$episode = $this->episodeRepository->fetchEpisodeForStation($station, $episode_id);
$podcastEpisodesLink = (string)$router->named(
$podcastEpisodesLink = $router->named(
'public:podcast:episodes',
[
'station_id' => $station->getId(),
@ -57,7 +57,7 @@ final class PodcastEpisodeAction
return $response->withRedirect($podcastEpisodesLink);
}
$feedLink = (string)$router->named(
$feedLink = $router->named(
'public:podcast:feed',
[
'station_id' => $station->getId(),

View File

@ -57,7 +57,7 @@ final class PodcastEpisodesAction
}
);
$podcastsLink = (string)$router->fromHere(
$podcastsLink = $router->fromHere(
'public:podcasts',
[
'station_id' => $station->getId(),
@ -69,7 +69,7 @@ final class PodcastEpisodesAction
return $response->withRedirect($podcastsLink);
}
$feedLink = (string)$router->named(
$feedLink = $router->named(
'public:podcast:feed',
[
'station_id' => $station->getId(),

View File

@ -136,7 +136,7 @@ final class PodcastFeedAction
$channelLink = $podcast->getLink();
if (empty($channelLink)) {
$channelLink = (string)$serverRequest->getRouter()->fromHere(
$channelLink = $serverRequest->getRouter()->fromHere(
routeName: 'public:podcast:episodes',
absolute: true
);
@ -237,7 +237,7 @@ final class PodcastFeedAction
);
if ($podcastsFilesystem->fileExists(Podcast::getArtPath($podcast->getIdRequired()))) {
$podcastArtworkSrc = (string)$this->router->fromHere(
$podcastArtworkSrc = $this->router->fromHere(
routeName: 'api:stations:podcast:art',
routeParams: ['podcast_id' => $podcast->getIdRequired() . '|' . $podcast->getArtUpdatedAt()],
absolute: true
@ -275,7 +275,7 @@ final class PodcastFeedAction
$episodeLink = $episode->getLink();
if (empty($episodeLink)) {
$episodeLink = (string)$this->router->fromHere(
$episodeLink = $this->router->fromHere(
routeName: 'public:podcast:episode',
routeParams: ['episode_id' => $episode->getId()],
absolute: true
@ -318,7 +318,7 @@ final class PodcastFeedAction
): RssEnclosure {
$rssEnclosure = new RssEnclosure();
$podcastMediaPlayUrl = (string)$this->router->fromHere(
$podcastMediaPlayUrl = $this->router->fromHere(
routeName: 'api:stations:podcast:episode:download',
routeParams: ['episode_id' => $episode->getId()],
absolute: true
@ -345,7 +345,7 @@ final class PodcastFeedAction
);
if ($podcastsFilesystem->fileExists(PodcastEpisode::getArtPath($episode->getIdRequired()))) {
$episodeArtworkSrc = (string)$this->router->fromHere(
$episodeArtworkSrc = $this->router->fromHere(
routeName: 'api:stations:podcast:episode:art',
routeParams: ['episode_id' => $episode->getId() . '|' . $episode->getArtUpdatedAt()],
absolute: true

View File

@ -45,7 +45,7 @@ final class RequestsAction
props: [
'customFields' => $this->customFieldRepo->fetchArray(),
'showAlbumArt' => !$customization->hideAlbumArt(),
'requestListUri' => (string)$router->named('api:requests:list', [
'requestListUri' => $router->named('api:requests:list', [
'station_id' => $station->getId(),
]),
],

View File

@ -42,7 +42,7 @@ final class ScheduleAction
'hide_footer' => true,
],
props: [
'scheduleUrl' => (string)$router->named('api:stations:schedule', [
'scheduleUrl' => $router->named('api:stations:schedule', [
'station_id' => $station->getId(),
]),
'stationName' => $station->getName(),

View File

@ -43,7 +43,7 @@ final class SetupController
Response $response
): ResponseInterface {
$current_step = $this->getSetupStep($request);
return $response->withRedirect((string)$request->getRouter()->named('setup:' . $current_step));
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
}
/**
@ -57,7 +57,7 @@ final class SetupController
// Verify current step.
$current_step = $this->getSetupStep($request);
if ($current_step !== 'register' && $this->environment->isProduction()) {
return $response->withRedirect((string)$request->getRouter()->named('setup:' . $current_step));
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
}
$csrf = $request->getCsrf();
@ -97,7 +97,7 @@ final class SetupController
$acl = $request->getAcl();
$acl->reload();
return $response->withRedirect((string)$request->getRouter()->named('setup:index'));
return $response->withRedirect($request->getRouter()->named('setup:index'));
} catch (Throwable $e) {
$error = $e->getMessage();
}
@ -127,9 +127,11 @@ final class SetupController
// Verify current step.
$current_step = $this->getSetupStep($request);
if ($current_step !== 'station' && $this->environment->isProduction()) {
return $response->withRedirect((string)$request->getRouter()->named('setup:' . $current_step));
return $response->withRedirect($request->getRouter()->named('setup:' . $current_step));
}
$router = $request->getRouter();
return $request->getView()->renderVuePage(
response: $response,
component: 'Vue_SetupStation',
@ -138,8 +140,8 @@ final class SetupController
props: array_merge(
$this->stationFormComponent->getProps($request),
[
'createUrl' => (string)$request->getRouter()->named('api:admin:stations'),
'continueUrl' => (string)$request->getRouter()->named('setup:settings'),
'createUrl' => $router->named('api:admin:stations'),
'continueUrl' => $router->named('setup:settings'),
]
)
);
@ -158,7 +160,7 @@ final class SetupController
// Verify current step.
$current_step = $this->getSetupStep($request);
if ($current_step !== 'settings' && $this->environment->isProduction()) {
return $response->withRedirect((string)$router->named('setup:' . $current_step));
return $response->withRedirect($router->named('setup:' . $current_step));
}
return $request->getView()->renderVuePage(
@ -167,11 +169,11 @@ final class SetupController
id: 'setup-settings',
title: __('System Settings'),
props: [
'apiUrl' => (string)$router->named('api:admin:settings', [
'apiUrl' => $router->named('api:admin:settings', [
'group' => Entity\Settings::GROUP_GENERAL,
]),
'releaseChannel' => $this->version->getReleaseChannelEnum()->value,
'continueUrl' => (string)$router->named('dashboard'),
'continueUrl' => $router->named('dashboard'),
],
);
}
@ -188,7 +190,7 @@ final class SetupController
): ResponseInterface {
$request->getFlash()->addMessage('<b>' . __('Setup has already been completed!') . '</b>', Flash::ERROR);
return $response->withRedirect((string)$request->getRouter()->named('dashboard'));
return $response->withRedirect($request->getRouter()->named('dashboard'));
}
/**

View File

@ -23,7 +23,7 @@ final class BulkMediaAction
id: 'station-bulk-media',
title: __('Bulk Media Import/Export'),
props: [
'apiUrl' => (string)$router->fromHere('api:stations:files:bulk'),
'apiUrl' => $router->fromHere('api:stations:files:bulk'),
],
);
}

View File

@ -60,8 +60,8 @@ final class EditLiquidsoapConfigAction
id: 'station-liquidsoap-config',
title: __('Edit Liquidsoap Configuration'),
props: [
'settingsUrl' => (string)$router->fromHere('api:stations:liquidsoap-config'),
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'settingsUrl' => $router->fromHere('api:stations:liquidsoap-config'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
'config' => $areas,
'sections' => $configSections,
],

View File

@ -25,7 +25,7 @@ final class FallbackAction
id: 'station-fallback',
title: __('Custom Fallback File'),
props: [
'apiUrl' => (string)$router->fromHere('api:stations:fallback'),
'apiUrl' => $router->fromHere('api:stations:fallback'),
'recordHasFallback' => !empty($station->getFallbackPath()),
],
);

View File

@ -48,13 +48,13 @@ final class FilesAction
id: 'media-manager',
title: __('Music Files'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:files:list'),
'batchUrl' => (string)$router->fromHere('api:stations:files:batch'),
'uploadUrl' => (string)$router->fromHere('api:stations:files:upload'),
'listDirectoriesUrl' => (string)$router->fromHere('api:stations:files:directories'),
'mkdirUrl' => (string)$router->fromHere('api:stations:files:mkdir'),
'renameUrl' => (string)$router->fromHere('api:stations:files:rename'),
'quotaUrl' => (string)$router->fromHere('api:stations:quota', [
'listUrl' => $router->fromHere('api:stations:files:list'),
'batchUrl' => $router->fromHere('api:stations:files:batch'),
'uploadUrl' => $router->fromHere('api:stations:files:upload'),
'listDirectoriesUrl' => $router->fromHere('api:stations:files:directories'),
'mkdirUrl' => $router->fromHere('api:stations:files:mkdir'),
'renameUrl' => $router->fromHere('api:stations:files:rename'),
'quotaUrl' => $router->fromHere('api:stations:quota', [
'type' => Entity\Enums\StorageLocationTypes::StationMedia->value,
]),
'initialPlaylists' => $playlists,
@ -62,7 +62,7 @@ final class FilesAction
'validMimeTypes' => MimeType::getProcessableTypes(),
'stationTimeZone' => $station->getTimezone(),
'showSftp' => StationFeatures::Sftp->supportedForStation($station),
'sftpUrl' => (string)$router->fromHere('stations:sftp_users:index'),
'sftpUrl' => $router->fromHere('stations:sftp_users:index'),
'supportsImmediateQueue' => $backendEnum->isEnabled(),
],
);

View File

@ -22,8 +22,8 @@ final class HlsStreamsAction
id: 'station-hls-streams',
title: __('HLS Streams'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:hls_streams'),
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'listUrl' => $router->fromHere('api:stations:hls_streams'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
],
);
}

View File

@ -23,7 +23,7 @@ final class LogsAction
id: 'stations-help',
title: __('Help'),
props: [
'logsUrl' => (string)$router->fromHere('api:stations:logs'),
'logsUrl' => $router->fromHere('api:stations:logs'),
],
);
}

View File

@ -32,9 +32,9 @@ final class MountsAction
id: 'station-mounts',
title: __('Mount Points'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:mounts'),
'newIntroUrl' => (string)$router->fromHere('api:stations:mounts:new-intro'),
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'listUrl' => $router->fromHere('api:stations:mounts'),
'newIntroUrl' => $router->fromHere('api:stations:mounts:new-intro'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
'stationFrontendType' => $station->getFrontendType(),
'showAdvanced' => $settings->getEnableAdvancedFeatures(),
],

View File

@ -32,10 +32,10 @@ final class PlaylistsAction
id: 'station-playlist',
title: __('Playlists'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:playlists'),
'scheduleUrl' => (string)$router->fromHere('api:stations:playlists:schedule'),
'filesUrl' => (string)$router->fromHere('stations:files:index'),
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'listUrl' => $router->fromHere('api:stations:playlists'),
'scheduleUrl' => $router->fromHere('api:stations:playlists:schedule'),
'filesUrl' => $router->fromHere('stations:files:index'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
'stationTimeZone' => $station->getTimezone(),
'useManualAutoDj' => $station->useManualAutoDJ(),
'enableAdvancedFeatures' => $settings->getEnableAdvancedFeatures(),

View File

@ -32,10 +32,10 @@ final class PodcastsAction
id: 'station-podcasts',
title: __('Podcasts'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:podcasts'),
'newArtUrl' => (string)$router->fromHere('api:stations:podcasts:new-art'),
'stationUrl' => (string)$router->fromHere('stations:index:index'),
'quotaUrl' => (string)$router->fromHere('api:stations:quota', [
'listUrl' => $router->fromHere('api:stations:podcasts'),
'newArtUrl' => $router->fromHere('api:stations:podcasts:new-art'),
'stationUrl' => $router->fromHere('stations:index:index'),
'quotaUrl' => $router->fromHere('api:stations:quota', [
'type' => Entity\Enums\StorageLocationTypes::StationPodcasts->value,
]),
'locale' => substr($locale->value, 0, 2),

View File

@ -83,7 +83,7 @@ final class ProfileController
'enableStreamers' => $station->getEnableStreamers(),
'enablePublicPage' => $station->getEnablePublicPage(),
'enableOnDemand' => $station->getEnableOnDemand(),
'profileApiUri' => (string)$router->fromHere('api:stations:profile'),
'profileApiUri' => $router->fromHere('api:stations:profile'),
'hasStarted' => $station->getHasStarted(),
// ACL
@ -96,82 +96,82 @@ final class ProfileController
// Header
'stationName' => $station->getName(),
'stationDescription' => $station->getDescription(),
'manageProfileUri' => (string)$router->fromHere('stations:profile:edit'),
'manageProfileUri' => $router->fromHere('stations:profile:edit'),
// Now Playing
'backendSkipSongUri' => (string)$router->fromHere('api:stations:backend', ['do' => 'skip']),
'backendDisconnectStreamerUri' => (string)$router->fromHere(
'backendSkipSongUri' => $router->fromHere('api:stations:backend', ['do' => 'skip']),
'backendDisconnectStreamerUri' => $router->fromHere(
'api:stations:backend',
['do' => 'disconnect']
),
// Requests
'requestsViewUri' => (string)$router->fromHere('stations:reports:requests'),
'requestsToggleUri' => (string)$router->fromHere(
'requestsViewUri' => $router->fromHere('stations:reports:requests'),
'requestsToggleUri' => $router->fromHere(
'stations:profile:toggle',
['feature' => 'requests', 'csrf' => $csrf]
),
// Streamers
'streamersViewUri' => (string)$router->fromHere('stations:streamers:index'),
'streamersToggleUri' => (string)$router->fromHere(
'streamersViewUri' => $router->fromHere('stations:streamers:index'),
'streamersToggleUri' => $router->fromHere(
'stations:profile:toggle',
['feature' => 'streamers', 'csrf' => $csrf]
),
// Public Pages
'publicPageUri' => (string)$router->named(
'publicPageUri' => $router->named(
routeName: 'public:index',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicPageEmbedUri' => (string)$router->named(
'publicPageEmbedUri' => $router->named(
routeName: 'public:index',
routeParams: ['station_id' => $station->getShortName(), 'embed' => 'embed'],
absolute: true
),
'publicWebDjUri' => (string)$router->named(
'publicWebDjUri' => $router->named(
routeName: 'public:dj',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicOnDemandUri' => (string)$router->named(
'publicOnDemandUri' => $router->named(
routeName: 'public:ondemand',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicPodcastsUri' => (string)$router->named(
'publicPodcastsUri' => $router->named(
routeName: 'public:podcasts',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicScheduleUri' => (string)$router->named(
'publicScheduleUri' => $router->named(
routeName: 'public:schedule',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicOnDemandEmbedUri' => (string)$router->named(
'publicOnDemandEmbedUri' => $router->named(
routeName: 'public:ondemand',
routeParams: ['station_id' => $station->getShortName(), 'embed' => 'embed'],
absolute: true
),
'publicRequestEmbedUri' => (string)$router->named(
'publicRequestEmbedUri' => $router->named(
routeName: 'public:embedrequests',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicHistoryEmbedUri' => (string)$router->named(
'publicHistoryEmbedUri' => $router->named(
routeName: 'public:history',
routeParams: ['station_id' => $station->getShortName()],
absolute: true
),
'publicScheduleEmbedUri' => (string)$router->named(
'publicScheduleEmbedUri' => $router->named(
routeName: 'public:schedule',
routeParams: ['station_id' => $station->getShortName(), 'embed' => 'embed'],
absolute: true
),
'togglePublicPageUri' => (string)$router->fromHere(
'togglePublicPageUri' => $router->fromHere(
routeName: 'stations:profile:toggle',
routeParams: ['feature' => 'public', 'csrf' => $csrf]
),
@ -181,18 +181,18 @@ final class ProfileController
'frontendAdminPassword' => $frontendConfig->getAdminPassword(),
'frontendSourcePassword' => $frontendConfig->getSourcePassword(),
'frontendRelayPassword' => $frontendConfig->getRelayPassword(),
'frontendRestartUri' => (string)$router->fromHere('api:stations:frontend', ['do' => 'restart']),
'frontendStartUri' => (string)$router->fromHere('api:stations:frontend', ['do' => 'start']),
'frontendStopUri' => (string)$router->fromHere('api:stations:frontend', ['do' => 'stop']),
'frontendRestartUri' => $router->fromHere('api:stations:frontend', ['do' => 'restart']),
'frontendStartUri' => $router->fromHere('api:stations:frontend', ['do' => 'start']),
'frontendStopUri' => $router->fromHere('api:stations:frontend', ['do' => 'stop']),
// Backend
'numSongs' => (int)$num_songs,
'numPlaylists' => (int)$num_playlists,
'manageMediaUri' => (string)$router->fromHere('stations:files:index'),
'managePlaylistsUri' => (string)$router->fromHere('stations:playlists:index'),
'backendRestartUri' => (string)$router->fromHere('api:stations:backend', ['do' => 'restart']),
'backendStartUri' => (string)$router->fromHere('api:stations:backend', ['do' => 'start']),
'backendStopUri' => (string)$router->fromHere('api:stations:backend', ['do' => 'stop']),
'manageMediaUri' => $router->fromHere('stations:files:index'),
'managePlaylistsUri' => $router->fromHere('stations:playlists:index'),
'backendRestartUri' => $router->fromHere('api:stations:backend', ['do' => 'restart']),
'backendStartUri' => $router->fromHere('api:stations:backend', ['do' => 'start']),
'backendStopUri' => $router->fromHere('api:stations:backend', ['do' => 'stop']),
],
);
}
@ -212,8 +212,8 @@ final class ProfileController
props: array_merge(
$this->stationFormComponent->getProps($request),
[
'editUrl' => (string)$router->fromHere('api:stations:profile:edit'),
'continueUrl' => (string)$router->fromHere('stations:profile:index'),
'editUrl' => $router->fromHere('api:stations:profile:edit'),
'continueUrl' => $router->fromHere('stations:profile:index'),
]
)
);
@ -247,6 +247,6 @@ final class ProfileController
$this->em->persist($station);
$this->em->flush();
return $response->withRedirect((string)$request->getRouter()->fromHere('stations:profile:index'));
return $response->withRedirect($request->getRouter()->fromHere('stations:profile:index'));
}
}

View File

@ -24,8 +24,8 @@ final class QueueAction
id: 'station-queue',
title: __('Upcoming Song Queue'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:queue'),
'clearUrl' => (string)$router->fromHere('api:stations:queue:clear'),
'listUrl' => $router->fromHere('api:stations:queue'),
'clearUrl' => $router->fromHere('api:stations:queue:clear'),
'stationTimeZone' => $station->getTimezone(),
],
);

View File

@ -23,8 +23,8 @@ final class RemotesAction
id: 'station-remotes',
title: __('Remote Relays'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:remotes'),
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'listUrl' => $router->fromHere('api:stations:remotes'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
],
);
}

View File

@ -24,7 +24,7 @@ final class ListenersAction
id: 'station-report-listeners',
title: __('Listeners'),
props: [
'apiUrl' => (string)$router->fromHere('api:listeners:index'),
'apiUrl' => $router->fromHere('api:listeners:index'),
'stationTz' => $station->getTimezone(),
]
);

View File

@ -40,13 +40,13 @@ final class OverviewAction
props: [
'stationTz' => $request->getStation()->getTimezone(),
'showFullAnalytics' => Entity\Enums\AnalyticsLevel::All === $analyticsLevel,
'listenersByTimePeriodUrl' => (string)$router->fromHere('api:stations:reports:overview-charts'),
'bestAndWorstUrl' => (string)$router->fromHere('api:stations:reports:best-and-worst'),
'byStreamUrl' => (string)$router->fromHere('api:stations:reports:by-stream'),
'byBrowserUrl' => (string)$router->fromHere('api:stations:reports:by-browser'),
'byCountryUrl' => (string)$router->fromHere('api:stations:reports:by-country'),
'byClientUrl' => (string)$router->fromHere('api:stations:reports:by-client'),
'listeningTimeUrl' => (string)$router->fromHere('api:stations:reports:by-listening-time'),
'listenersByTimePeriodUrl' => $router->fromHere('api:stations:reports:overview-charts'),
'bestAndWorstUrl' => $router->fromHere('api:stations:reports:best-and-worst'),
'byStreamUrl' => $router->fromHere('api:stations:reports:by-stream'),
'byBrowserUrl' => $router->fromHere('api:stations:reports:by-browser'),
'byCountryUrl' => $router->fromHere('api:stations:reports:by-country'),
'byClientUrl' => $router->fromHere('api:stations:reports:by-client'),
'listeningTimeUrl' => $router->fromHere('api:stations:reports:by-listening-time'),
]
);
}

View File

@ -24,8 +24,8 @@ final class RequestsAction
id: 'station-report-requests',
title: __('Song Requests'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:reports:requests'),
'clearUrl' => (string)$router->fromHere('api:stations:reports:requests:clear'),
'listUrl' => $router->fromHere('api:stations:reports:requests'),
'clearUrl' => $router->fromHere('api:stations:reports:requests:clear'),
'stationTimeZone' => $station->getTimezone(),
]
);

View File

@ -29,7 +29,7 @@ final class SoundExchangeAction
id: 'station-report-soundexchange',
title: __('SoundExchange Report'),
props: [
'apiUrl' => (string)$router->fromHere('api:stations:reports:soundexchange'),
'apiUrl' => $router->fromHere('api:stations:reports:soundexchange'),
'startDate' => $defaultStartDate,
'endDate' => $defaultEndDate,
]

View File

@ -24,7 +24,7 @@ final class TimelineAction
id: 'station-report-timeline',
title: __('Song Playback Timeline'),
props: [
'baseApiUrl' => (string)$router->fromHere('api:stations:history'),
'baseApiUrl' => $router->fromHere('api:stations:history'),
'stationTimeZone' => $station->getTimezone(),
]
);

View File

@ -37,7 +37,7 @@ final class SftpUsersAction
id: 'station-sftp-users',
title: __('SFTP Users'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:sftp-users'),
'listUrl' => $router->fromHere('api:stations:sftp-users'),
'connectionInfo' => [
'url' => (string)$baseUrl,
'ip' => $this->acCentral->getIp(),

View File

@ -36,9 +36,9 @@ final class StreamersAction
id: 'station-streamers',
title: __('Streamer/DJ Accounts'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:streamers'),
'newArtUrl' => (string)$router->fromHere('api:stations:streamers:new-art'),
'scheduleUrl' => (string)$router->fromHere('api:stations:streamers:schedule'),
'listUrl' => $router->fromHere('api:stations:streamers'),
'newArtUrl' => $router->fromHere('api:stations:streamers:new-art'),
'scheduleUrl' => $router->fromHere('api:stations:streamers:schedule'),
'stationTimeZone' => $station->getTimezone(),
'connectionInfo' => [
'serverUrl' => $settings->getBaseUrl(),

View File

@ -24,9 +24,9 @@ final class UploadStereoToolConfigAction
id: 'stations-stereo-tool-config',
title: __('Upload Stereo Tool Configuration'),
props: [
'restartStatusUrl' => (string)$router->fromHere('api:stations:restart-status'),
'restartStatusUrl' => $router->fromHere('api:stations:restart-status'),
'recordHasStereoToolConfiguration' => !empty($backendConfig->getStereoToolConfigurationPath()),
'apiUrl' => (string)$router->fromHere('api:stations:stereo_tool_config'),
'apiUrl' => $router->fromHere('api:stations:stereo_tool_config'),
],
);
}

View File

@ -35,7 +35,7 @@ final class WebhooksAction
id: 'station-webhooks',
title: __('Web Hooks'),
props: [
'listUrl' => (string)$router->fromHere('api:stations:webhooks'),
'listUrl' => $router->fromHere('api:stations:webhooks'),
'webhookTypes' => $webhookConfig['webhooks'],
'webhookTriggers' => $webhookConfig['triggers'],
'enableAdvancedFeatures' => $settings->getEnableAdvancedFeatures(),

View File

@ -118,7 +118,7 @@ final class NowPlayingApiGenerator
$live->broadcast_start = $broadcastStart;
if (0 !== $currentStreamer->getArtUpdatedAt()) {
$live->art = $this->router->named(
$live->art = $this->router->namedAsUri(
routeName: 'api:stations:streamer:art',
routeParams: [
'station_id' => $station->getIdRequired(),

View File

@ -68,7 +68,7 @@ final class SongApiGenerator
$mediaId .= '-' . $mediaUpdatedTimestamp;
}
return $this->router->named(
return $this->router->namedAsUri(
routeName: 'api:stations:media:art',
routeParams: [
'station_id' => $station->getId(),
@ -87,7 +87,7 @@ final class SongApiGenerator
if ($isNowPlaying && null !== $station) {
$currentStreamer = $station->getCurrentStreamer();
if (null !== $currentStreamer && 0 !== $currentStreamer->getArtUpdatedAt()) {
return $this->router->named(
return $this->router->namedAsUri(
routeName: 'api:stations:streamer:art',
routeParams: [
'station_id' => $station->getIdRequired(),

View File

@ -36,15 +36,15 @@ final class StationApiGenerator
$response->is_public = $station->getEnablePublicPage();
$response->listen_url = $frontend?->getStreamUrl($station, $baseUri);
$response->public_player_url = (string)$this->router->named(
$response->public_player_url = $this->router->named(
'public:index',
['station_id' => $station->getShortName()]
);
$response->playlist_pls_url = (string)$this->router->named(
$response->playlist_pls_url = $this->router->named(
'public:playlist',
['station_id' => $station->getShortName(), 'format' => 'pls']
);
$response->playlist_m3u_url = (string)$this->router->named(
$response->playlist_m3u_url = $this->router->named(
'public:playlist',
['station_id' => $station->getShortName(), 'format' => 'm3u']
);

View File

@ -189,7 +189,7 @@ final class ErrorHandler extends \Slim\Handlers\ErrorHandler
$response = $sessionPersistence->persistSession($session, $response);
/** @var Response $response */
return $response->withRedirect((string)$this->router->named('account:login'));
return $response->withRedirect($this->router->named('account:login'));
}
if ($this->exception instanceof PermissionDeniedException) {
@ -219,7 +219,7 @@ final class ErrorHandler extends \Slim\Handlers\ErrorHandler
// Bounce back to homepage for permission-denied users.
/** @var Response $response */
return $response->withRedirect((string)$this->router->named('home'));
return $response->withRedirect($this->router->named('home'));
}
/** @var Response $response */

View File

@ -6,14 +6,13 @@ namespace App\Http;
use App\Entity;
use App\Traits\RequestAwareTrait;
use FastRoute\RouteParser\Std;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\Psr7\UriResolver;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UriInterface;
use Slim\Interfaces\RouteCollectorInterface;
use Slim\Interfaces\RouteInterface;
use Slim\Interfaces\RouteParserInterface;
use Slim\Routing\RouteContext;
final class Router implements RouterInterface
@ -24,24 +23,10 @@ final class Router implements RouterInterface
private ?RouteInterface $currentRoute = null;
private readonly array $routes;
private readonly Std $routeParser;
public function __construct(
private readonly Entity\Repository\SettingsRepository $settingsRepo,
RouteCollectorInterface $routeCollector
private readonly RouteParserInterface $routeParser,
) {
$routes = [];
foreach ($routeCollector->getRoutes() as $route) {
$routeName = $route->getName();
if (null !== $routeName) {
$routes[$routeName] = $route;
}
}
$this->routes = $routes;
$this->routeParser = new Std();
}
public function setRequest(?ServerRequestInterface $request): void
@ -107,10 +92,7 @@ final class Router implements RouterInterface
return $baseUrl;
}
/**
* @inheritDoc
*/
public function fromHereWithQuery(
public function fromHereWithQueryAsUri(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
@ -120,13 +102,23 @@ final class Router implements RouterInterface
$queryParams = array_merge($this->request->getQueryParams(), $queryParams);
}
return $this->fromHereAsUri($routeName, $routeParams, $queryParams, $absolute);
}
public function fromHereWithQuery(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string {
if ($this->request instanceof ServerRequestInterface) {
$queryParams = array_merge($this->request->getQueryParams(), $queryParams);
}
return $this->fromHere($routeName, $routeParams, $queryParams, $absolute);
}
/**
* @inheritDoc
*/
public function fromHere(
public function fromHereAsUri(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
@ -146,84 +138,56 @@ final class Router implements RouterInterface
);
}
return $this->namedAsUri($routeName, $routeParams, $queryParams, $absolute);
}
public function fromHere(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string {
if (null !== $this->currentRoute) {
if (null === $routeName) {
$routeName = $this->currentRoute->getName();
}
$routeParams = array_merge($this->currentRoute->getArguments(), $routeParams);
}
if (null === $routeName) {
throw new InvalidArgumentException(
'Cannot specify a null route name if no existing route is configured.'
);
}
return $this->named($routeName, $routeParams, $queryParams, $absolute);
}
/**
* @inheritDoc
*/
public function named(
public function namedAsUri(
string $routeName,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): UriInterface {
$relativeUri = $this->getRelativeUri($routeName, $routeParams, $queryParams);
$relativeUri = $this->routeParser->relativeUrlFor($routeName, $routeParams, $queryParams);
return ($absolute)
? self::resolveUri($this->getBaseUrl(), $relativeUri, true)
: $relativeUri;
: self::createUri($relativeUri);
}
private function getRelativeUri(string $routeName, array $data = [], array $queryParams = []): UriInterface
{
if (!isset($this->routes[$routeName])) {
throw new \InvalidArgumentException('Named route does not exist for name: ' . $routeName);
}
public function named(
string $routeName,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string {
$relativeUri = $this->routeParser->relativeUrlFor($routeName, $routeParams, $queryParams);
$pattern = $this->routes[$routeName]->getPattern();
$segments = [];
$segmentName = '';
/*
* $routes is an associative array of expressions representing a route as multiple segments
* There is an expression for each optional parameter plus one without the optional parameters
* The most specific is last, hence why we reverse the array before iterating over it
*/
foreach (array_reverse($this->routeParser->parse($pattern)) as $expression) {
foreach ($expression as $segment) {
/*
* Each $segment is either a string or an array of strings
* containing optional parameters of an expression
*/
if (is_string($segment)) {
$segments[] = $segment;
continue;
}
/** @var string[] $segment */
/*
* If we don't have a data element for this segment in the provided $data
* we cancel testing to move onto the next expression with a less specific item
*/
if (!array_key_exists($segment[0], $data)) {
$segments = [];
$segmentName = $segment[0];
break;
}
$segments[] = $data[$segment[0]];
}
/*
* If we get to this logic block we have found all the parameters
* for the provided $data which means we don't need to continue testing
* less specific expressions
*/
if (!empty($segments)) {
break;
}
}
if (empty($segments)) {
throw new InvalidArgumentException('Missing data for URL segment: ' . $segmentName);
}
$url = new Uri(implode('', $segments));
return ($queryParams)
? $url->withQuery(http_build_query($queryParams))
: $url;
return ($absolute)
? (string)self::resolveUri($this->getBaseUrl(), $relativeUri, true)
: $relativeUri;
}
/**
@ -240,7 +204,7 @@ final class Router implements RouterInterface
bool $absolute = false
): UriInterface {
if (!$rel instanceof UriInterface) {
$rel = new Uri($rel);
$rel = self::createUri($rel);
}
if (!$absolute) {
@ -258,4 +222,9 @@ final class Router implements RouterInterface
return UriResolver::resolve($base, $rel);
}
public static function createUri(string $uri): UriInterface
{
return new Uri($uri);
}
}

View File

@ -19,46 +19,61 @@ interface RouterInterface
/**
* Simpler format for calling "named" routes with parameters.
*
* @param string $routeName
* @param array $routeParams
* @param array $queryParams
* @param boolean $absolute Whether to include the full URL.
*/
public function named(
string $routeName,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string;
/**
* Same as above, but returning a UriInterface.
*/
public function namedAsUri(
string $routeName,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): UriInterface;
/**
* Return a named route based on the current page and its route arguments.
*
* @param string|null $routeName
* @param array $routeParams
* @param array $queryParams
* @param bool $absolute
*/
public function fromHere(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string;
/**
* Same as above, but returns a UriInterface.
*/
public function fromHereAsUri(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): UriInterface;
/**
* Same as $this->fromHere(), but merging the current GET query parameters into the request as well.
*
* @param string|null $routeName
* @param array $routeParams
* @param array $queryParams
* @param bool $absolute
*/
public function fromHereWithQuery(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): string;
/**
* Same as above, but returns a UriInterface.
*/
public function fromHereWithQueryAsUri(
?string $routeName = null,
array $routeParams = [],
array $queryParams = [],
bool $absolute = false
): UriInterface;
}

View File

@ -59,7 +59,7 @@ final class BaseUrlCheck
$notification->body = implode(' ', $notificationBodyParts);
$notification->type = Flash::WARNING;
$notification->actionLabel = __('System Settings');
$notification->actionUrl = (string)$router->named('admin:settings:index');
$notification->actionUrl = $router->named('admin:settings:index');
$event->addNotification($notification);
}

View File

@ -52,7 +52,7 @@ final class RecentBackupCheck
$router = $request->getRouter();
$notification->actionLabel = __('Backups');
$notification->actionUrl = (string)$router->named('admin:backups:index');
$notification->actionUrl = $router->named('admin:backups:index');
$event->addNotification($notification);
}

View File

@ -40,7 +40,7 @@ final class ServiceCheck
$router = $request->getRouter();
$notification->actionLabel = __('Administration');
$notification->actionUrl = (string)$router->named('admin:index:index');
$notification->actionUrl = $router->named('admin:index:index');
// phpcs:enable
$event->addNotification($notification);

View File

@ -59,7 +59,7 @@ final class SyncTaskCheck
$router = $request->getRouter();
$notification->actionLabel = __('System Debugger');
$notification->actionUrl = (string)$router->named('admin:debug:index');
$notification->actionUrl = $router->named('admin:debug:index');
// phpcs:enable
$event->addNotification($notification);

View File

@ -157,21 +157,21 @@ final class Paginator implements IteratorAggregate, Countable
}
$pageLinks = [];
$pageLinks['first'] = (string)$this->router->fromHereWithQuery(null, [], ['page' => 1]);
$pageLinks['first'] = $this->router->fromHereWithQuery(null, [], ['page' => 1]);
$prevPage = $this->paginator->hasPreviousPage()
? $this->paginator->getPreviousPage()
: 1;
$pageLinks['previous'] = (string)$this->router->fromHereWithQuery(null, [], ['page' => $prevPage]);
$pageLinks['previous'] = $this->router->fromHereWithQuery(null, [], ['page' => $prevPage]);
$nextPage = $this->paginator->hasNextPage()
? $this->paginator->getNextPage()
: $this->paginator->getNbPages();
$pageLinks['next'] = (string)$this->router->fromHereWithQuery(null, [], ['page' => $nextPage]);
$pageLinks['next'] = $this->router->fromHereWithQuery(null, [], ['page' => $nextPage]);
$pageLinks['last'] = (string)$this->router->fromHereWithQuery(null, [], ['page' => $totalPages]);
$pageLinks['last'] = $this->router->fromHereWithQuery(null, [], ['page' => $totalPages]);
return $response->withJson(
[

Some files were not shown because too many files have changed in this diff Show More