diff --git a/src/AppFactory.php b/src/AppFactory.php index 585d2e23e..ce1426648 100644 --- a/src/AppFactory.php +++ b/src/AppFactory.php @@ -10,9 +10,9 @@ use App\Http\Factory\ResponseFactory; use App\Http\Factory\ServerRequestFactory; use DI; use Monolog\ErrorHandler; +use Monolog\Logger; use Monolog\Registry; use Psr\EventDispatcher\EventDispatcherInterface; -use Psr\Log\LoggerInterface; use Slim\App; use Slim\Factory\ServerRequestCreatorFactory; use Slim\Handlers\Strategies\RequestResponseNamedArgs; @@ -102,7 +102,7 @@ class AppFactory $di = $containerBuilder->build(); // Monolog setup - $logger = $di->get(LoggerInterface::class); + $logger = $di->get(Logger::class); $errorHandler = new ErrorHandler($logger); $errorHandler->registerFatalHandler(); diff --git a/src/Entity/Repository/ListenerRepository.php b/src/Entity/Repository/ListenerRepository.php index 18be5f1fc..97bbe6d43 100644 --- a/src/Entity/Repository/ListenerRepository.php +++ b/src/Entity/Repository/ListenerRepository.php @@ -9,10 +9,10 @@ use App\Doctrine\Repository; use App\Entity; use App\Service\DeviceDetector; use App\Service\IpGeolocation; +use App\Utilities\Logger; use Carbon\CarbonImmutable; use DateTimeInterface; use Doctrine\DBAL\Connection; -use Monolog\Registry; use NowPlaying\Result\Client; use Throwable; @@ -185,7 +185,7 @@ final class ListenerRepository extends Repository $record['device_browser_family'] = $this->truncateNullableString($browserResult->browserFamily, 150); $record['device_os_family'] = $this->truncateNullableString($browserResult->osFamily, 150); } catch (Throwable $e) { - Registry::getInstance('app')->error('Device Detector error: ' . $e->getMessage(), [ + Logger::getInstance()->error('Device Detector error: ' . $e->getMessage(), [ 'user_agent' => $userAgent, 'exception' => $e, ]); @@ -208,7 +208,7 @@ final class ListenerRepository extends Repository $record['location_lat'] = $ipInfo->lat; $record['location_lon'] = $ipInfo->lon; } catch (Throwable $e) { - Registry::getInstance('app')->error('IP Geolocation error: ' . $e->getMessage(), [ + Logger::getInstance()->error('IP Geolocation error: ' . $e->getMessage(), [ 'ip' => $ip, 'exception' => $e, ]); diff --git a/src/Entity/Repository/StationMediaRepository.php b/src/Entity/Repository/StationMediaRepository.php index 1506a332e..a4ab5bca9 100644 --- a/src/Entity/Repository/StationMediaRepository.php +++ b/src/Entity/Repository/StationMediaRepository.php @@ -13,11 +13,11 @@ use App\Media\AlbumArt; use App\Media\MetadataManager; use App\Media\RemoteAlbumArt; use App\Service\AudioWaveform; +use App\Utilities\Logger; use Azura\Files\ExtendedFilesystemInterface; use Exception; use Generator; use League\Flysystem\FilesystemException; -use Monolog\Registry; use const JSON_PRETTY_PRINT; use const JSON_THROW_ON_ERROR; @@ -292,7 +292,7 @@ final class StationMediaRepository extends Repository try { $this->writeAlbumArt($media, $artwork, $fs); } catch (Exception $exception) { - Registry::getInstance('app')->error( + Logger::getInstance()->error( sprintf( 'Album Artwork for "%s" could not be processed: "%s"', $filePath, diff --git a/src/Entity/Settings.php b/src/Entity/Settings.php index 596f95d3a..b04202d92 100644 --- a/src/Entity/Settings.php +++ b/src/Entity/Settings.php @@ -76,18 +76,25 @@ class Settings implements Stringable public function getBaseUrlAsUri(): ?UriInterface { - return Urls::getUri($this->base_url); + return Urls::tryParseUserUrl( + $this->base_url, + 'System Base URL', + ); } public function setBaseUrl(?string $baseUrl): void { - if (null === $baseUrl) { + if (empty($baseUrl)) { $this->base_url = null; return; } // Filter the base URL to avoid trailing slashes and other problems. - $baseUri = new Uri($baseUrl); + $baseUri = Urls::parseUserUrl( + $baseUrl, + 'System Base URL' + ); + if ('' === $baseUri->getScheme()) { $baseUri = $baseUri->withScheme('http'); } @@ -375,7 +382,10 @@ class Settings implements Stringable public function getHomepageRedirectUrlAsUri(): ?UriInterface { - return Urls::getUri($this->homepage_redirect_url); + return Urls::tryParseUserUrl( + $this->homepage_redirect_url, + 'Homepage Redirect URL', + ); } public function setHomepageRedirectUrl(?string $homepageRedirectUrl): void @@ -397,7 +407,10 @@ class Settings implements Stringable public function getDefaultAlbumArtUrlAsUri(): ?UriInterface { - return Urls::getUri($this->default_album_art_url); + return Urls::tryParseUserUrl( + $this->default_album_art_url, + 'Default Album Art URL', + ); } public function setDefaultAlbumArtUrl(?string $defaultAlbumArtUrl): void diff --git a/src/Entity/Station.php b/src/Entity/Station.php index c5d943688..8b32d017e 100644 --- a/src/Entity/Station.php +++ b/src/Entity/Station.php @@ -921,7 +921,10 @@ class Station implements Stringable, IdentifiableEntityInterface public function getDefaultAlbumArtUrlAsUri(): ?UriInterface { - return Urls::getUri($this->default_album_art_url); + return Urls::tryParseUserUrl( + $this->default_album_art_url, + 'Station ' . $this->__toString() . ' Default Album Art URL' + ); } /** diff --git a/src/Entity/StationMount.php b/src/Entity/StationMount.php index add1eb9e4..cd44073ae 100644 --- a/src/Entity/StationMount.php +++ b/src/Entity/StationMount.php @@ -240,7 +240,10 @@ class StationMount implements public function getRelayUrlAsUri(): ?UriInterface { - return Urls::getUri($this->relay_url); + return Urls::tryParseUserUrl( + $this->relay_url, + 'Mount Point ' . $this->__toString() . ' Relay URL' + ); } public function setRelayUrl(?string $relay_url = null): void @@ -312,7 +315,10 @@ class StationMount implements public function getCustomListenUrlAsUri(): ?UriInterface { - return Urls::getUri($this->custom_listen_url); + return Urls::tryParseUserUrl( + $this->custom_listen_url, + 'Mount Point ' . $this->__toString() . ' Listen URL' + ); } public function setCustomListenUrl(?string $custom_listen_url = null): void diff --git a/src/Entity/StationRemote.php b/src/Entity/StationRemote.php index e35274da5..231fd36fe 100644 --- a/src/Entity/StationRemote.php +++ b/src/Entity/StationRemote.php @@ -11,7 +11,6 @@ use App\Radio\Enums\StreamProtocols; use App\Radio\Remote\AbstractRemote; use App\Utilities; use Doctrine\ORM\Mapping as ORM; -use GuzzleHttp\Psr7\Uri; use InvalidArgumentException; use Psr\Http\Message\UriInterface; use Stringable; @@ -297,17 +296,24 @@ class StationRemote implements public function getUrlAsUri(): UriInterface { - return new Uri($this->url); + return Utilities\Urls::parseUserUrl( + $this->url, + 'Remote Relay ' . $this->__toString() . ' URL' + ); } public function setUrl(string $url): void { - if (!empty($url) && !str_starts_with($url, 'http')) { - /** @noinspection HttpUrlsUsage */ - $url = 'http://' . $url; - } + if (empty($url)) { + $this->url = ''; + } else { + $uri = Utilities\Urls::parseUserUrl( + $url, + 'Remote Relay URL' + ); - $this->url = $this->truncateString($url); + $this->url = $this->truncateString((string)$uri); + } } /* diff --git a/src/Middleware/Module/Api.php b/src/Middleware/Module/Api.php index c649fe8ea..76ef7d601 100644 --- a/src/Middleware/Module/Api.php +++ b/src/Middleware/Module/Api.php @@ -71,7 +71,10 @@ class Api $origins = []; foreach ($rawOrigins as $rawOrigin) { - $uri = Urls::getUri($rawOrigin); + $uri = Urls::tryParseUserUrl( + $rawOrigin, + 'System Setting Access-Control-Allowo-Origin' + ); if (null !== $uri) { if (empty($uri->getScheme())) { $origins[] = (string)($uri->withScheme('http')); diff --git a/src/Radio/Frontend/Icecast.php b/src/Radio/Frontend/Icecast.php index 54bda114b..b06aa05f5 100644 --- a/src/Radio/Frontend/Icecast.php +++ b/src/Radio/Frontend/Icecast.php @@ -109,10 +109,8 @@ class Icecast extends AbstractFrontend $frontendConfig = $station->getFrontendConfig(); $configDir = $station->getRadioConfigDir(); - $settings = $this->settingsRepo->readSettings(); - - $settingsBaseUrl = $settings->getBaseUrl() ?: ''; - $baseUrl = Utilities\Urls::getUri($settingsBaseUrl) ?? new Uri('http://localhost'); + $settingsBaseUrl = $this->settingsRepo->readSettings()->getBaseUrlAsUri(); + $baseUrl = $settingsBaseUrl ?? new Uri('http://localhost'); [$certPath, $certKey] = Acme::getCertificatePaths(); diff --git a/src/Utilities/Logger.php b/src/Utilities/Logger.php new file mode 100644 index 000000000..1a294d4af --- /dev/null +++ b/src/Utilities/Logger.php @@ -0,0 +1,16 @@ +getMessage()), + previous: $e + ); + } + } + + public static function tryParseUserUrl( + ?string $url, + string $context + ): ?UriInterface { + if (empty($url)) { + return null; + } + + try { + return self::parseUserUrl($url, $context); + } catch (\Exception $e) { + Logger::getInstance()->error( + sprintf('Could not parse %s URL "%s": %s', $context, $url, $e->getMessage()), + [ + 'exception' => $e, + ] + ); + return null; + } + } } diff --git a/src/Webhook/Connector/MatomoAnalytics.php b/src/Webhook/Connector/MatomoAnalytics.php index 6be4658de..176333f0f 100644 --- a/src/Webhook/Connector/MatomoAnalytics.php +++ b/src/Webhook/Connector/MatomoAnalytics.php @@ -7,10 +7,10 @@ namespace App\Webhook\Connector; use App\Entity; use App\Http\RouterInterface; use App\Radio\Adapters; +use App\Utilities\Urls; use Doctrine\ORM\EntityManagerInterface; use GuzzleHttp\Client; use GuzzleHttp\Exception\TransferException; -use GuzzleHttp\Psr7\Uri; use Monolog\Logger; use Psr\Http\Message\UriInterface; @@ -67,7 +67,11 @@ class MatomoAnalytics extends AbstractConnector } // Build Matomo URI - $apiUrl = (new Uri($config['matomo_url']))->withPath('/matomo.php'); + $apiUrl = Urls::parseUserUrl( + $config['matomo_url'], + 'Matomo Analytics URL', + )->withPath('/matomo.php'); + $apiToken = $config['token'] ?? null; $stationName = $station->getName();