2016-10-07 02:41:04 +00:00
|
|
|
<?php
|
2018-08-04 22:05:14 +00:00
|
|
|
namespace App;
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2019-08-07 04:33:55 +00:00
|
|
|
use App\Entity;
|
2019-07-31 18:47:12 +00:00
|
|
|
use App\Service\NChan;
|
2018-03-19 01:31:43 +00:00
|
|
|
use Gettext\Translator;
|
2018-10-04 23:12:12 +00:00
|
|
|
use GuzzleHttp\Psr7\Uri;
|
2019-09-04 18:00:51 +00:00
|
|
|
use Locale;
|
2019-08-07 04:33:55 +00:00
|
|
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
2018-10-04 23:12:12 +00:00
|
|
|
use Psr\Http\Message\UriInterface;
|
2019-09-04 18:00:51 +00:00
|
|
|
use const LC_ALL;
|
2016-10-07 02:41:04 +00:00
|
|
|
|
|
|
|
class Customization
|
|
|
|
{
|
2019-03-06 06:08:42 +00:00
|
|
|
public const DEFAULT_TIMEZONE = 'UTC';
|
|
|
|
public const DEFAULT_LOCALE = 'en_US.UTF-8';
|
2019-03-14 01:49:19 +00:00
|
|
|
public const DEFAULT_THEME = 'light';
|
2018-12-28 02:17:08 +00:00
|
|
|
|
2019-03-06 06:08:42 +00:00
|
|
|
/** @var Entity\User|null */
|
2019-12-07 12:19:49 +00:00
|
|
|
protected ?Entity\User $user = null;
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2019-12-07 12:19:49 +00:00
|
|
|
protected Entity\Repository\SettingsRepository $settingsRepo;
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2019-12-07 12:19:49 +00:00
|
|
|
protected ?string $locale = null;
|
2019-08-21 22:33:47 +00:00
|
|
|
|
2019-09-29 07:50:24 +00:00
|
|
|
public function __construct(Entity\Repository\SettingsRepository $settingsRepo)
|
2016-10-07 02:41:04 +00:00
|
|
|
{
|
2019-09-29 07:50:24 +00:00
|
|
|
$this->settingsRepo = $settingsRepo;
|
2019-09-04 18:00:51 +00:00
|
|
|
}
|
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
/**
|
|
|
|
* Set the currently active/logged in user.
|
|
|
|
*
|
|
|
|
* @param Entity\User $user
|
|
|
|
*/
|
|
|
|
public function setUser(Entity\User $user = null): void
|
|
|
|
{
|
|
|
|
$this->user = $user;
|
|
|
|
}
|
|
|
|
|
2018-02-01 11:49:40 +00:00
|
|
|
/**
|
2018-07-03 22:51:05 +00:00
|
|
|
* Initialize timezone and locale settings for the current user, and write them as attributes to the request.
|
|
|
|
*
|
2019-08-21 22:33:47 +00:00
|
|
|
* @param Request|null $request
|
2019-09-20 16:44:38 +00:00
|
|
|
*
|
2019-08-21 22:33:47 +00:00
|
|
|
* @return Request|null
|
2018-02-01 11:49:40 +00:00
|
|
|
*/
|
2019-08-21 22:33:47 +00:00
|
|
|
public function init(?Request $request = null): ?Request
|
2018-02-01 11:49:40 +00:00
|
|
|
{
|
2019-08-21 22:33:47 +00:00
|
|
|
$this->locale = $this->initLocale($request);
|
2018-03-19 01:31:43 +00:00
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
// Set up the PHP translator
|
2018-03-19 01:31:43 +00:00
|
|
|
$translator = new Translator();
|
|
|
|
|
2019-09-12 05:31:01 +00:00
|
|
|
$locale_base = Settings::getInstance()->getBaseDirectory() . '/resources/locale/compiled';
|
2019-09-04 18:00:51 +00:00
|
|
|
$locale_path = $locale_base . '/' . $this->locale . '.php';
|
2018-02-01 11:49:40 +00:00
|
|
|
|
2018-03-19 01:31:43 +00:00
|
|
|
if (file_exists($locale_path)) {
|
|
|
|
$translator->loadTranslations($locale_path);
|
2018-02-01 11:49:40 +00:00
|
|
|
}
|
2018-03-19 01:31:43 +00:00
|
|
|
|
|
|
|
$translator->register();
|
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
// Register translation superglobal functions
|
|
|
|
putenv('LANG=' . $this->locale);
|
2019-09-04 18:00:51 +00:00
|
|
|
setlocale(LC_ALL, $this->locale);
|
2018-02-01 11:49:40 +00:00
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
if ($request instanceof Request) {
|
|
|
|
$request = $request->withAttribute('locale', $this->locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $request;
|
2018-02-01 11:49:40 +00:00
|
|
|
}
|
|
|
|
|
2016-10-07 02:41:04 +00:00
|
|
|
/**
|
|
|
|
* Return the user-customized, browser-specified or system default locale.
|
|
|
|
*
|
2019-08-21 22:33:47 +00:00
|
|
|
* @param Request|null $request
|
2019-09-20 16:44:38 +00:00
|
|
|
*
|
2019-08-21 22:33:47 +00:00
|
|
|
* @return string|null
|
2016-10-07 02:41:04 +00:00
|
|
|
*/
|
2019-08-21 22:33:47 +00:00
|
|
|
protected function initLocale(?Request $request = null): ?string
|
2016-10-07 02:41:04 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
$settings = Settings::getInstance();
|
|
|
|
if ($settings->isTesting()) {
|
2019-08-21 23:42:57 +00:00
|
|
|
return self::DEFAULT_LOCALE;
|
|
|
|
}
|
|
|
|
|
2019-09-12 05:31:01 +00:00
|
|
|
$supported_locales = $settings['locale']['supported'];
|
2019-08-21 22:33:47 +00:00
|
|
|
$try_locales = [];
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2018-11-24 18:05:23 +00:00
|
|
|
// Prefer user-based profile locale.
|
2019-08-21 22:33:47 +00:00
|
|
|
if ($this->user !== null && !empty($this->user->getLocale()) && 'default' !== $this->user->getLocale()) {
|
|
|
|
$try_locales[] = $this->user->getLocale();
|
2018-11-24 18:05:23 +00:00
|
|
|
}
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2018-11-24 18:05:23 +00:00
|
|
|
// Attempt to load from browser headers.
|
2019-08-21 22:33:47 +00:00
|
|
|
if ($request instanceof Request) {
|
|
|
|
$server_params = $request->getServerParams();
|
2019-09-04 18:00:51 +00:00
|
|
|
$browser_locale = Locale::acceptFromHttp($server_params['HTTP_ACCEPT_LANGUAGE'] ?? null);
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
if (!empty($browser_locale)) {
|
2019-09-04 18:00:51 +00:00
|
|
|
$try_locales[] = substr($browser_locale, 0, 5) . '.UTF-8';
|
2019-08-21 22:33:47 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-24 18:05:23 +00:00
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
// Attempt to load from environment variable.
|
|
|
|
$env_locale = getenv('LANG');
|
|
|
|
if (!empty($env_locale)) {
|
2019-09-04 18:00:51 +00:00
|
|
|
$try_locales[] = substr($env_locale, 0, 5) . '.UTF-8';
|
2018-11-24 18:05:23 +00:00
|
|
|
}
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2019-09-04 18:00:51 +00:00
|
|
|
foreach ($try_locales as $exact_locale) {
|
2019-08-21 22:33:47 +00:00
|
|
|
// Prefer exact match.
|
|
|
|
if (isset($supported_locales[$exact_locale])) {
|
|
|
|
return $exact_locale;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use approximate match if available.
|
|
|
|
foreach ($supported_locales as $lang_code => $lang_name) {
|
2019-08-21 23:19:09 +00:00
|
|
|
if (strpos($exact_locale, substr($lang_code, 0, 2)) === 0) {
|
2019-08-21 22:33:47 +00:00
|
|
|
return $lang_code;
|
|
|
|
}
|
2017-12-14 18:04:58 +00:00
|
|
|
}
|
2017-01-24 00:35:16 +00:00
|
|
|
}
|
2016-10-07 02:41:04 +00:00
|
|
|
|
2018-11-24 18:05:23 +00:00
|
|
|
// Default to system option.
|
2019-08-21 22:33:47 +00:00
|
|
|
return self::DEFAULT_LOCALE;
|
|
|
|
}
|
2019-03-14 01:49:19 +00:00
|
|
|
|
2019-08-21 22:33:47 +00:00
|
|
|
/**
|
2019-10-04 03:12:15 +00:00
|
|
|
* @return string
|
2019-08-21 22:33:47 +00:00
|
|
|
*/
|
2019-10-04 03:12:15 +00:00
|
|
|
public function getLocale(): string
|
2019-08-21 22:33:47 +00:00
|
|
|
{
|
|
|
|
return $this->locale ?? self::DEFAULT_LOCALE;
|
2016-10-07 02:41:04 +00:00
|
|
|
}
|
|
|
|
|
2019-10-04 03:12:15 +00:00
|
|
|
/**
|
|
|
|
* @return string A shortened locale (minus .UTF-8) for use in Vue.
|
|
|
|
*/
|
|
|
|
public function getVueLocale(): string
|
|
|
|
{
|
2020-07-08 07:03:50 +00:00
|
|
|
return json_encode(substr($this->getLocale(), 0, 5), JSON_THROW_ON_ERROR);
|
2019-10-04 03:12:15 +00:00
|
|
|
}
|
|
|
|
|
2016-10-07 02:41:04 +00:00
|
|
|
/**
|
|
|
|
* Returns the user-customized or system default theme.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-07-08 07:03:50 +00:00
|
|
|
public function getTheme(): string
|
2016-10-07 02:41:04 +00:00
|
|
|
{
|
2017-08-17 18:28:48 +00:00
|
|
|
if ($this->user !== null && !empty($this->user->getTheme())) {
|
2019-03-14 01:49:19 +00:00
|
|
|
return $this->user->getTheme();
|
2016-10-07 02:41:04 +00:00
|
|
|
}
|
|
|
|
|
2019-03-14 01:49:19 +00:00
|
|
|
return self::DEFAULT_THEME;
|
2016-10-07 02:41:04 +00:00
|
|
|
}
|
2017-05-21 04:27:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the instance name for this AzuraCast instance.
|
|
|
|
*
|
|
|
|
* @return string|null
|
|
|
|
*/
|
2019-03-14 01:49:19 +00:00
|
|
|
public function getInstanceName(): ?string
|
2017-05-21 04:27:34 +00:00
|
|
|
{
|
|
|
|
static $instance_name;
|
|
|
|
|
|
|
|
if ($instance_name === null) {
|
2019-09-12 05:31:01 +00:00
|
|
|
$instance_name = $this->settingsRepo->getSetting(Entity\Settings::INSTANCE_NAME, '');
|
2017-05-21 04:27:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $instance_name;
|
|
|
|
}
|
2017-09-20 02:10:06 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the theme name to be used in public (non-logged-in) pages.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2019-03-14 01:49:19 +00:00
|
|
|
public function getPublicTheme(): string
|
2017-09-20 02:10:06 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return $this->settingsRepo->getSetting(Entity\Settings::PUBLIC_THEME, self::DEFAULT_THEME);
|
2017-09-20 02:10:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the administrator-supplied custom CSS for public (minimal layout) pages, if specified.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-07-08 07:03:50 +00:00
|
|
|
public function getCustomPublicCss(): string
|
2017-09-20 02:10:06 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_CSS_PUBLIC, '');
|
2017-09-20 02:10:06 +00:00
|
|
|
}
|
|
|
|
|
2018-02-28 15:25:33 +00:00
|
|
|
/**
|
|
|
|
* Return the administrator-supplied custom JS for public (minimal layout) pages, if specified.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-07-08 07:03:50 +00:00
|
|
|
public function getCustomPublicJs(): string
|
2018-02-28 15:25:33 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_JS_PUBLIC, '');
|
2018-02-28 15:25:33 +00:00
|
|
|
}
|
|
|
|
|
2017-09-20 02:10:06 +00:00
|
|
|
/**
|
|
|
|
* Return the administrator-supplied custom CSS for internal (full layout) pages, if specified.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
2020-07-08 07:03:50 +00:00
|
|
|
public function getCustomInternalCss(): string
|
2017-09-20 02:10:06 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return (string)$this->settingsRepo->getSetting(Entity\Settings::CUSTOM_CSS_INTERNAL, '');
|
2017-09-20 02:10:06 +00:00
|
|
|
}
|
2018-02-04 13:20:23 +00:00
|
|
|
|
2018-03-04 12:06:50 +00:00
|
|
|
/**
|
|
|
|
* Return whether to show or hide album art on public pages.
|
|
|
|
*
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function hideAlbumArt(): bool
|
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return (bool)$this->settingsRepo->getSetting(Entity\Settings::HIDE_ALBUM_ART, false);
|
2018-03-04 12:06:50 +00:00
|
|
|
}
|
2018-03-17 02:40:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the URL to use for songs with no specified album artwork, when artwork is displayed.
|
|
|
|
*
|
2020-05-03 01:28:08 +00:00
|
|
|
* @param Entity\Station|null $station
|
|
|
|
*
|
2018-10-04 23:12:12 +00:00
|
|
|
* @return UriInterface
|
2018-03-17 02:40:34 +00:00
|
|
|
*/
|
2020-05-03 01:28:08 +00:00
|
|
|
public function getDefaultAlbumArtUrl(?Entity\Station $station = null): UriInterface
|
2018-03-17 02:40:34 +00:00
|
|
|
{
|
2020-05-03 01:28:08 +00:00
|
|
|
if ($station instanceof Entity\Station) {
|
|
|
|
$stationCustomUrl = trim($station->getDefaultAlbumArtUrl());
|
|
|
|
|
|
|
|
if (!empty($stationCustomUrl)) {
|
|
|
|
return new Uri($stationCustomUrl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-12 05:31:01 +00:00
|
|
|
$custom_url = trim($this->settingsRepo->getSetting(Entity\Settings::DEFAULT_ALBUM_ART_URL));
|
2018-03-17 02:40:34 +00:00
|
|
|
|
|
|
|
if (!empty($custom_url)) {
|
2018-10-04 23:12:12 +00:00
|
|
|
return new Uri($custom_url);
|
2018-03-17 02:40:34 +00:00
|
|
|
}
|
|
|
|
|
2018-10-04 23:12:12 +00:00
|
|
|
return new Uri('/static/img/generic_song.jpg');
|
2018-03-17 02:40:34 +00:00
|
|
|
}
|
2018-10-17 03:50:14 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the calculated page title given branding settings and the application environment.
|
|
|
|
*
|
|
|
|
* @param string|null $title
|
2019-09-20 16:44:38 +00:00
|
|
|
*
|
2018-10-17 03:50:14 +00:00
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getPageTitle($title = null): string
|
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
$settings = Settings::getInstance();
|
|
|
|
|
2018-10-17 03:50:14 +00:00
|
|
|
if (!$this->hideProductName()) {
|
|
|
|
if ($title) {
|
2019-09-12 05:31:01 +00:00
|
|
|
$title .= ' - ' . $settings[Settings::APP_NAME];
|
2018-10-17 03:50:14 +00:00
|
|
|
} else {
|
2019-09-12 05:31:01 +00:00
|
|
|
$title = $settings[Settings::APP_NAME];
|
2018-10-17 03:50:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-12 05:31:01 +00:00
|
|
|
if (!$settings->isProduction()) {
|
|
|
|
$title = '(' . ucfirst($settings[Settings::APP_ENV]) . ') ' . $title;
|
2018-10-17 03:50:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $title;
|
|
|
|
}
|
2018-12-28 02:17:08 +00:00
|
|
|
|
2019-07-31 18:47:12 +00:00
|
|
|
/**
|
2019-09-04 18:00:51 +00:00
|
|
|
* Return whether to show or hide the AzuraCast name from public-facing pages.
|
|
|
|
*
|
2019-07-31 18:47:12 +00:00
|
|
|
* @return bool
|
|
|
|
*/
|
2019-09-04 18:00:51 +00:00
|
|
|
public function hideProductName(): bool
|
2019-07-31 18:47:12 +00:00
|
|
|
{
|
2019-09-12 05:31:01 +00:00
|
|
|
return (bool)$this->settingsRepo->getSetting(Entity\Settings::HIDE_PRODUCT_NAME, false);
|
2019-07-31 18:47:12 +00:00
|
|
|
}
|
|
|
|
|
2018-12-28 02:17:08 +00:00
|
|
|
/**
|
2019-09-04 18:00:51 +00:00
|
|
|
* @return bool
|
2018-12-28 02:17:08 +00:00
|
|
|
*/
|
2019-09-04 18:00:51 +00:00
|
|
|
public function useWebSocketsForNowPlaying(): bool
|
2018-12-28 02:17:08 +00:00
|
|
|
{
|
2019-09-04 18:00:51 +00:00
|
|
|
if (!NChan::isSupported()) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-12-28 02:17:08 +00:00
|
|
|
|
2019-09-12 05:31:01 +00:00
|
|
|
return (bool)$this->settingsRepo->getSetting(Entity\Settings::NOWPLAYING_USE_WEBSOCKETS, false);
|
2018-12-28 02:17:08 +00:00
|
|
|
}
|
|
|
|
|
2019-09-29 21:26:46 +00:00
|
|
|
/**
|
|
|
|
* Initialize the CLI without instantiating the Doctrine DB stack (allowing cache clearing, etc.).
|
|
|
|
*/
|
|
|
|
public static function initCli(): void
|
|
|
|
{
|
|
|
|
$translator = new Translator();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO: Load translations from environment locale.
|
|
|
|
$locale_base = Settings::getInstance()->getBaseDirectory() . '/resources/locale/compiled';
|
|
|
|
$locale_path = $locale_base . '/' . $this->locale . '.php';
|
|
|
|
|
|
|
|
if (file_exists($locale_path)) {
|
|
|
|
$translator->loadTranslations($locale_path);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
$translator->register();
|
|
|
|
}
|
|
|
|
|
2018-02-28 15:25:33 +00:00
|
|
|
}
|