hasIdentity()) { $userId = null; } else { $auth = Zend_Auth::getInstance(); $userId = $auth->getIdentity()->id; } return $userId; } /** * @param bool $isUserValue is true when we are setting a value for the current user * @param mixed $key * @param mixed $value */ private static function setValue($key, $value, $isUserValue = false) { $con = Propel::getConnection(CcPrefPeer::DATABASE_NAME); // We are using row-level locking in Postgres via "FOR UPDATE" instead of a transaction here // because sometimes this function needs to be called while a transaction is already started. try { /* Comment this out while we reevaluate it in favor of a unique constraint static::_lock($con); */ $userId = self::getUserId(); if ($isUserValue && is_null($userId)) { throw new Exception("User id can't be null for a user preference {$key}."); } // Check if key already exists $sql = 'SELECT valstr FROM cc_pref' . ' WHERE keystr = :key'; $paramMap = []; $paramMap[':key'] = $key; // For user specific preference, check if id matches as well if ($isUserValue) { $sql .= ' AND subjid = :id'; $paramMap[':id'] = $userId; } $sql .= ' FOR UPDATE'; $result = Application_Common_Database::prepareAndExecute( $sql, $paramMap, Application_Common_Database::ROW_COUNT, PDO::FETCH_ASSOC, $con ); $paramMap = []; if ($result > 1) { // this case should not happen. $caller = debug_backtrace()[1]['function']; throw new Exception('Invalid number of results returned. Should be ' . "0 or 1, but is '{$result}' instead, caller={$caller}"); } if ($result == 1) { // result found if (!$isUserValue) { // system pref $sql = 'UPDATE cc_pref' . ' SET subjid = NULL, valstr = :value' . ' WHERE keystr = :key'; } else { // user pref $sql = 'UPDATE cc_pref' . ' SET valstr = :value' . ' WHERE keystr = :key AND subjid = :id'; $paramMap[':id'] = $userId; } } else { // result not found if (!$isUserValue) { // system pref $sql = 'INSERT INTO cc_pref (keystr, valstr)' . ' VALUES (:key, :value)'; } else { // user pref $sql = 'INSERT INTO cc_pref (subjid, keystr, valstr)' . ' VALUES (:id, :key, :value)'; $paramMap[':id'] = $userId; } } $paramMap[':key'] = $key; $paramMap[':value'] = $value; Application_Common_Database::prepareAndExecute( $sql, $paramMap, Application_Common_Database::EXECUTE, PDO::FETCH_ASSOC, $con ); } catch (Exception $e) { header('HTTP/1.0 503 Service Unavailable'); Logging::info('Database error: ' . $e->getMessage()); exit; } } /** * Given a PDO connection, lock the cc_pref table for the current transaction. * * Creates a table level lock, which defaults to ACCESS EXCLUSIVE mode; * see https://www.postgresql.org/docs/9.1/static/explicit-locking.html * * @param PDO $con */ private static function _lock($con) { // If we're not in a transaction, a lock is pointless if (!$con->inTransaction()) { return; } // Don't specify NOWAIT here; we should block on obtaining this lock // in case we're handling simultaneous requests. // Locks only last until the end of the transaction, so we shouldn't have to // worry about this causing any noticeable difference in request processing speed $sql = 'LOCK TABLE cc_pref'; $st = $con->prepare($sql); $st->execute(); } /** * @param string $key the preference key string * @param bool|false $isUserValue select the preference for the current user * @param bool|false $forceDefault only look for default (no user ID) values * * @return mixed the preference value */ private static function getValue($key, $isUserValue = false, $forceDefault = false) { try { $userId = null; if ($isUserValue) { // This is nested in here because so we can still use getValue() when the session hasn't started yet. $userId = self::getUserId(); if (is_null($userId)) { throw new Exception("User id can't be null for a user preference."); } } // Check if key already exists $sql = 'SELECT COUNT(*) FROM cc_pref' . ' WHERE keystr = :key'; $paramMap = []; $paramMap[':key'] = $key; // For user specific preference, check if id matches as well if ($isUserValue) { $sql .= ' AND subjid = :id'; $paramMap[':id'] = $userId; } elseif ($forceDefault) { $sql .= ' AND subjid IS NULL'; } $result = Application_Common_Database::prepareAndExecute($sql, $paramMap, Application_Common_Database::COLUMN); // return an empty string if the result doesn't exist. if ($result == 0) { $res = ''; } else { $sql = 'SELECT valstr FROM cc_pref' . ' WHERE keystr = :key'; $paramMap = []; $paramMap[':key'] = $key; // For user specific preference, check if id matches as well if ($isUserValue) { $sql .= ' AND subjid = :id'; $paramMap[':id'] = $userId; } $result = Application_Common_Database::prepareAndExecute($sql, $paramMap, Application_Common_Database::COLUMN); $res = ($result !== false) ? $result : ''; } return $res; } catch (Exception $e) { header('HTTP/1.0 503 Service Unavailable'); Logging::info('Could not connect to database: ' . $e); exit; } } public static function GetHeadTitle() { $title = self::getValue('station_name'); if (empty($title)) { $title = PRODUCT_NAME; } return $title; } public static function SetHeadTitle($title, $view = null) { self::setValue('station_name', $title); // in case this is called from airtime-saas script if ($view !== null) { // set session variable to new station name so that html title is updated. // should probably do this in a view helper to keep this controller as minimal as possible. $view->headTitle()->exchangeArray([]); // clear headTitle ArrayObject $view->headTitle(self::GetHeadTitle()); } $eventType = 'update_station_name'; $md = ['station_name' => $title]; Application_Model_RabbitMq::SendMessageToPypo($eventType, $md); } /** * Set the furthest date that a never-ending show * should be populated until. * * @param DateTime $dateTime * A row from cc_show_days table */ public static function SetShowsPopulatedUntil($dateTime) { $dateTime->setTimezone(new DateTimeZone('UTC')); self::setValue('shows_populated_until', $dateTime->format(DEFAULT_TIMESTAMP_FORMAT)); } /** * Get the furthest date that a never-ending show * should be populated until. * * Returns null if the value hasn't been set, otherwise returns * a DateTime object representing the date. * * @return DateTime (in UTC Timezone) */ public static function GetShowsPopulatedUntil() { $date = self::getValue('shows_populated_until'); if ($date == '') { return null; } return new DateTime($date, new DateTimeZone('UTC')); } public static function SetDefaultCrossfadeDuration($duration) { self::setValue('default_crossfade_duration', $duration); } public static function GetDefaultCrossfadeDuration() { $duration = self::getValue('default_crossfade_duration'); if ($duration === '') { // the default value of the fade is 00.5 return '0'; } return $duration; } public static function SetDefaultFadeIn($fade) { self::setValue('default_fade_in', $fade); } public static function GetDefaultFadeIn() { $fade = self::getValue('default_fade_in'); if ($fade === '') { // the default value of the fade is 00.5 return '0.5'; } return $fade; } public static function SetDefaultFadeOut($fade) { self::setValue('default_fade_out', $fade); } public static function GetDefaultFadeOut() { $fade = self::getValue('default_fade_out'); if ($fade === '') { // the default value of the fade is 0.5 return '0.5'; } return $fade; } public static function SetDefaultFade($fade) { self::setValue('default_fade', $fade); } public static function SetDefaultTransitionFade($fade) { self::setValue('default_transition_fade', $fade); $eventType = 'update_transition_fade'; $md = ['transition_fade' => $fade]; Application_Model_RabbitMq::SendMessageToPypo($eventType, $md); } public static function GetDefaultTransitionFade() { $transition_fade = self::getValue('default_transition_fade'); return ($transition_fade == '') ? '0.000' : $transition_fade; } public static function SetStreamLabelFormat($type) { self::setValue('stream_label_format', $type); $eventType = 'update_stream_format'; $md = ['stream_format' => $type]; Application_Model_RabbitMq::SendMessageToPypo($eventType, $md); } public static function GetStreamLabelFormat() { return self::getValue('stream_label_format'); } public static function getOffAirMeta() { return self::getValue('off_air_meta'); } public static function setOffAirMeta($offAirMeta) { self::setValue('off_air_meta', $offAirMeta); Application_Model_RabbitMq::SendMessageToPypo( 'update_message_offline', ['message_offline' => $offAirMeta] ); } public static function GetStationName() { return self::getValue('station_name'); } public static function SetStationName($station_name) { self::setValue('station_name', $station_name); } public static function SetAllow3rdPartyApi($bool) { self::setValue('third_party_api', $bool); } public static function GetAllow3rdPartyApi() { $val = self::getValue('third_party_api'); return (strlen($val) == 0) ? '1' : $val; } public static function SetPodcastAlbumOverride($bool) { self::setValue('podcast_album_override', $bool); } public static function GetPodcastAlbumOverride() { $val = self::getValue('podcast_album_override'); return $val === '1' ? true : false; } public static function SetPodcastAutoSmartblock($bool) { self::setValue('podcast_auto_smartblock', $bool); } public static function GetPodcastAutoSmartblock() { $val = self::getValue('podcast_auto_smartblock'); return $val === '1' ? true : false; } public static function SetTrackTypeDefault($tracktype) { self::setValue('tracktype_default', $tracktype); } public static function GetTrackTypeDefault() { return self::getValue('tracktype_default'); } public static function GetIntroPlaylist() { return self::getValue('intro_playlist'); } public static function GetOutroPlaylist() { return self::getValue('outro_playlist'); } public static function SetIntroPlaylist($playlist) { self::setValue('intro_playlist', $playlist); } public static function SetOutroPlaylist($playlist) { self::setValue('outro_playlist', $playlist); } public static function SetPhone($phone) { self::setValue('phone', $phone); } public static function GetPhone() { return self::getValue('phone'); } public static function SetEmail($email) { self::setValue('email', $email); } public static function GetEmail() { return self::getValue('email'); } public static function SetStationWebSite($site) { self::setValue('station_website', $site); } public static function GetStationWebSite() { return self::getValue('station_website'); } public static function SetSupportFeedback($feedback) { self::setValue('support_feedback', $feedback); } public static function GetSupportFeedback() { return self::getValue('support_feedback'); } public static function SetPublicise($publicise) { self::setValue('publicise', $publicise); } public static function GetPublicise() { return self::getValue('publicise'); } public static function SetRegistered($registered) { self::setValue('registered', $registered); } public static function GetRegistered() { return self::getValue('registered'); } public static function SetStationCountry($country) { self::setValue('country', $country); } public static function GetStationCountry() { return self::getValue('country'); } public static function SetStationCity($city) { self::setValue('city', $city); } public static function GetStationCity() { return self::getValue('city'); } public static function SetStationDescription($description) { self::setValue('description', $description); } public static function GetStationDescription() { $description = self::getValue('description'); if (!empty($description)) { return $description; } return sprintf(_('Powered by %s'), SAAS_PRODUCT_BRANDING_NAME); } // Returns station default timezone (from preferences) public static function GetDefaultTimezone() { return Config::get('general.timezone'); } public static function SetUserTimezone($timezone = null) { self::setValue('user_timezone', $timezone, true); } public static function GetUserTimezone() { $timezone = self::getValue('user_timezone', true); if (!$timezone) { return self::GetDefaultTimezone(); } return $timezone; } // Always attempts to returns the current user's personal timezone setting public static function GetTimezone() { $userId = self::getUserId(); if (!is_null($userId)) { return self::GetUserTimezone(); } return self::GetDefaultTimezone(); } // This is the language setting on preferences page public static function SetDefaultLocale($locale) { self::setValue('locale', $locale); } public static function GetDefaultLocale() { return self::getValue('locale'); } public static function GetUserLocale() { $locale = self::getValue('user_locale', true); // empty() checks for null and empty strings - more robust than !val if (empty($locale)) { return self::GetDefaultLocale(); } return $locale; } public static function SetUserLocale($locale = null) { // When a new user is created they will get the default locale // setting which the admin sets on preferences page if (is_null($locale)) { $locale = self::GetDefaultLocale(); } self::setValue('user_locale', $locale, true); } public static function GetLocale() { $userId = self::getUserId(); if (!is_null($userId)) { return self::GetUserLocale(); } return self::GetDefaultLocale(); } public static function SetStationLogo($imagePath) { if (empty($imagePath)) { Logging::info('Removed station logo'); } $image = @file_get_contents($imagePath); $image = base64_encode($image); self::setValue('logoImage', $image); } public static function GetStationLogo() { $logoImage = self::getValue('logoImage'); if (!empty($logoImage)) { return $logoImage; } // We return the Airtime logo if no logo is set in the database. // airtime_logo.png is stored under the public directory $image = @file_get_contents(ROOT_PATH . '/public/' . DEFAULT_LOGO_FILE); return base64_encode($image); } public static function SetUniqueId($id) { self::setValue('uniqueId', $id); } public static function GetUniqueId() { return self::getValue('uniqueId'); } public static function GetCountryList() { $sql = 'SELECT * FROM cc_country'; $res = Application_Common_Database::prepareAndExecute($sql, []); $out = []; $out[''] = _('Select Country'); foreach ($res as $r) { $out[$r['isocode']] = $r['name']; } return $out; } public static function GetSystemInfo($returnArray = false, $p_testing = false) { exec('/usr/bin/airtime-check-system --no-color', $output); $output = preg_replace('/\s+/', ' ', $output); $systemInfoArray = []; foreach ($output as $key => &$out) { $info = explode('=', $out); if (isset($info[1])) { $key = str_replace(' ', '_', trim($info[0])); $key = strtoupper($key); if ( $key == 'WEB_SERVER' || $key == 'CPU' || $key == 'OS' || $key == 'TOTAL_RAM' || $key == 'FREE_RAM' || $key == 'AIRTIME_VERSION' || $key == 'KERNAL_VERSION' || $key == 'MACHINE_ARCHITECTURE' || $key == 'TOTAL_MEMORY_MBYTES' || $key == 'TOTAL_SWAP_MBYTES' || $key == 'PLAYOUT_ENGINE_CPU_PERC' ) { if ($key == 'AIRTIME_VERSION') { // remove hash tag on the version string $version = explode('+', $info[1]); $systemInfoArray[$key] = $version[0]; } else { $systemInfoArray[$key] = $info[1]; } } } } $outputArray = []; $outputArray['LIVE_DURATION'] = Application_Model_LiveLog::GetLiveShowDuration($p_testing); $outputArray['SCHEDULED_DURATION'] = Application_Model_LiveLog::GetScheduledDuration($p_testing); $outputArray['STATION_NAME'] = self::GetStationName(); $outputArray['PHONE'] = self::GetPhone(); $outputArray['EMAIL'] = self::GetEmail(); $outputArray['STATION_WEB_SITE'] = self::GetStationWebSite(); $outputArray['STATION_COUNTRY'] = self::GetStationCountry(); $outputArray['STATION_CITY'] = self::GetStationCity(); $outputArray['STATION_DESCRIPTION'] = self::GetStationDescription(); // get web server info if (isset($systemInfoArray['AIRTIME_VERSION_URL'])) { $url = $systemInfoArray['AIRTIME_VERSION_URL']; $index = strpos($url, '/api/'); $url = substr($url, 0, $index); $headerInfo = get_headers(trim($url), 1); $outputArray['WEB_SERVER'] = $headerInfo['Server'][0]; } $outputArray['NUM_OF_USERS'] = Application_Model_User::getUserCount(); $outputArray['NUM_OF_SONGS'] = Application_Model_StoredFile::getFileCount(); $outputArray['NUM_OF_PLAYLISTS'] = Application_Model_Playlist::getPlaylistCount(); $outputArray['NUM_OF_SCHEDULED_PLAYLISTS'] = Application_Model_Schedule::getSchduledPlaylistCount(); $outputArray['NUM_OF_PAST_SHOWS'] = Application_Model_ShowInstance::GetShowInstanceCount(gmdate(DEFAULT_TIMESTAMP_FORMAT)); $outputArray['UNIQUE_ID'] = self::GetUniqueId(); $outputArray['INSTALL_METHOD'] = self::GetInstallMethod(); $outputArray['NUM_OF_STREAMS'] = self::GetNumOfStreams(); $outputArray['STREAM_INFO'] = Application_Model_StreamSetting::getStreamInfoForDataCollection(); $outputArray = array_merge($systemInfoArray, $outputArray); $outputString = "\n"; foreach ($outputArray as $key => $out) { if ($key == 'STREAM_INFO') { $outputString .= $key . " :\n"; foreach ($out as $s_info) { foreach ($s_info as $k => $v) { $outputString .= "\t" . strtoupper($k) . ' : ' . $v . "\n"; } } } else { $outputString .= $key . ' : ' . $out . "\n"; } } if ($returnArray) { $outputArray['PROMOTE'] = self::GetPublicise(); $outputArray['LOGOIMG'] = self::GetStationLogo(); return $outputArray; } return $outputString; } public static function GetInstallMethod() { $easy_install = file_exists('/usr/bin/airtime-easy-setup'); $debian_install = file_exists('/var/lib/dpkg/info/airtime.config'); if ($debian_install) { if ($easy_install) { return 'easy_install'; } return 'debian_install'; } return 'manual_install'; } public static function SetRemindMeDate($p_never = false) { if ($p_never) { self::setValue('remindme', -1); } else { $weekAfter = mktime(0, 0, 0, gmdate('m'), gmdate('d') + 7, gmdate('Y')); self::setValue('remindme', $weekAfter); } } public static function GetRemindMeDate() { return self::getValue('remindme'); } public static function SetImportTimestamp() { $now = time(); if (self::GetImportTimestamp() + 5 < $now) { self::setValue('import_timestamp', $now); } } public static function GetImportTimestamp() { return (int) self::getValue('import_timestamp'); } public static function SetPrivacyPolicyCheck($flag) { self::setValue('privacy_policy', $flag); } public static function GetPrivacyPolicyCheck() { return self::getValue('privacy_policy'); } public static function GetNumOfStreams() { return count(Config::get('stream.outputs.merged')); } public static function SetEnableStreamConf($bool) { self::setValue('enable_stream_conf', $bool); } public static function GetEnableStreamConf() { if (self::getValue('enable_stream_conf') == null) { return 'true'; } return self::getValue('enable_stream_conf'); } public static function GetSchemaVersion() { CcPrefPeer::clearInstancePool(); // Ensure we don't get a cached Propel object (cached DB results) // because we're updating this version number within this HTTP request as well. // New versions use schema_version $pref = CcPrefQuery::create() ->filterByKeystr('schema_version') ->findOne(); if (empty($pref)) { // Pre-2.5.2 releases all used this ambiguous "system_version" key to represent both the code and schema versions... $pref = CcPrefQuery::create() ->filterByKeystr('system_version') ->findOne(); } return $pref->getValStr(); } public static function SetSchemaVersion($version) { self::setValue('schema_version', $version); } public static function GetLatestVersion() { $config = Config::getConfig(); $latest = json_decode(self::getValue('latest_version')); $nextCheck = self::getValue('latest_version_nextcheck'); if ($latest && $nextCheck > time()) { return $latest; } $rss = new SimplePie(); $rss->set_feed_url([LIBRETIME_UPDATE_FEED]); $rss->enable_cache(false); $rss->init(); $rss->handle_content_type(); // get all available versions ut to default github api limit $versions = []; foreach ($rss->get_items() as $item) { $versions[] = $item->get_title(); } $latest = $versions; self::setValue('latest_version_nextcheck', strtotime('+1 week')); if (empty($latest)) { return [$config['airtime_version']]; } self::setValue('latest_version', json_encode($latest)); return $latest; } public static function SetLatestVersion($version) { $pattern = '/^[0-9]+\.[0-9]+\.[0-9]+/'; if (preg_match($pattern, $version)) { self::setValue('latest_version', $version); } } public static function GetLatestLink() { $link = self::getValue('latest_link'); if ($link == null || strlen($link) == 0) { return LIBRETIME_WHATS_NEW_URL; } return $link; } public static function SetLatestLink($link) { $pattern = '#^(http|https|ftp)://' . '([a-zA-Z0-9]+\.)*[a-zA-Z0-9]+' . '(/[a-zA-Z0-9\-\.\_\~\:\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=]+)*/?$#'; if (preg_match($pattern, $link)) { self::setValue('latest_link', $link); } } public static function SetWeekStartDay($day) { self::setValue('week_start_day', $day); } public static function GetWeekStartDay() { $val = self::getValue('week_start_day'); return (strlen($val) == 0) ? '0' : $val; } /** * Stores the last timestamp of user updating stream setting. */ public static function SetStreamUpdateTimestamp() { $now = time(); self::setValue('stream_update_timestamp', $now); } /** * Gets the last timestamp of user updating stream setting. */ public static function GetStreamUpdateTimestemp() { $update_time = self::getValue('stream_update_timestamp'); return ($update_time == null) ? 0 : $update_time; } public static function GetClientId() { return self::getValue('client_id'); } public static function SetClientId($id) { if (is_numeric($id)) { self::setValue('client_id', $id); } else { Logging::warn("Attempting to set client_id to invalid value: {$id}"); } } // User specific preferences start /** * Sets the time scale preference (agendaDay/agendaWeek/month) in Calendar. * * @param $timeScale new time scale */ public static function SetCalendarTimeScale($timeScale) { self::setValue('calendar_time_scale', $timeScale, true /* user specific */); } /** * Retrieves the time scale preference for the current user. * Defaults to month if no entry exists. */ public static function GetCalendarTimeScale() { $val = self::getValue('calendar_time_scale', true /* user specific */); if (strlen($val) == 0) { $val = 'month'; } return $val; } /** * Sets the number of entries to show preference in library under Playlist Builder. * * @param $numEntries new number of entries to show */ public static function SetLibraryNumEntries($numEntries) { self::setValue('library_num_entries', $numEntries, true /* user specific */); } /** * Retrieves the number of entries to show preference in library under Playlist Builder. * Defaults to 10 if no entry exists. */ public static function GetLibraryNumEntries() { $val = self::getValue('library_num_entries', true /* user specific */); if (strlen($val) == 0) { $val = '10'; } return $val; } /** * Sets the time interval preference in Calendar. * * @param $timeInterval new time interval */ public static function SetCalendarTimeInterval($timeInterval) { self::setValue('calendar_time_interval', $timeInterval, true /* user specific */); } /** * Retrieves the time interval preference for the current user. * Defaults to 30 min if no entry exists. */ public static function GetCalendarTimeInterval() { $val = self::getValue('calendar_time_interval', true /* user specific */); return (strlen($val) == 0) ? '30' : $val; } public static function SetDiskQuota($value) { self::setValue('disk_quota', $value, false); } public static function GetDiskQuota() { $val = self::getValue('disk_quota'); return empty($val) ? 2147483648 : $val; // If there is no value for disk quota, return 2GB } public static function SetLiveStreamMasterUsername($value) { self::setValue('live_stream_master_username', $value, false); } public static function GetLiveStreamMasterUsername() { return self::getValue('live_stream_master_username'); } public static function SetLiveStreamMasterPassword($value) { self::setValue('live_stream_master_password', $value, false); } public static function GetLiveStreamMasterPassword() { return self::getValue('live_stream_master_password'); } public static function SetSourceStatus($sourcename, $status) { self::setValue($sourcename, $status, false); } public static function GetSourceStatus($sourcename) { $value = self::getValue($sourcename); return !($value == null || $value == 'false'); } public static function SetSourceSwitchStatus($sourcename, $status) { self::setValue($sourcename . '_switch', $status, false); } public static function GetSourceSwitchStatus($sourcename) { // Scheduled play switch should always be "on". // Even though we've hidden this element in the dashboard we should // always make sure it's on or else a station's stream could go offline. if ($sourcename == 'scheduled_play') { return 'on'; } $value = self::getValue($sourcename . '_switch'); return ($value == null || $value == 'off') ? 'off' : 'on'; } public static function GetMasterDJSourceConnectionURL() { if (Config::has('stream.inputs.main.public_url') && Config::get('stream.inputs.main.public_url')) { return Config::get('stream.inputs.main.public_url'); } $host = Config::get('general.public_url_raw')->getHost(); $port = Application_Model_StreamSetting::getMasterLiveStreamPort(); $mount = Application_Model_StreamSetting::getMasterLiveStreamMountPoint(); $secure = Application_Model_StreamSetting::getMasterLiveStreamSecure(); $scheme = $secure ? 'https' : 'http'; return "{$scheme}://{$host}:{$port}/{$mount}"; } public static function GetLiveDJSourceConnectionURL() { if (Config::has('stream.inputs.show.public_url') && Config::get('stream.inputs.show.public_url')) { return Config::get('stream.inputs.show.public_url'); } $host = Config::get('general.public_url_raw')->getHost(); $port = Application_Model_StreamSetting::getDjLiveStreamPort(); $mount = Application_Model_StreamSetting::getDjLiveStreamMountPoint(); $secure = Application_Model_StreamSetting::getDjLiveStreamSecure(); $scheme = $secure ? 'https' : 'http'; return "{$scheme}://{$host}:{$port}/{$mount}"; } public static function SetAutoTransition($value) { self::setValue('auto_transition', $value, false); } public static function GetAutoTransition() { return self::getValue('auto_transition'); } public static function SetAutoSwitch($value) { self::setValue('auto_switch', $value, false); } public static function GetAutoSwitch() { return self::getValue('auto_switch'); } // User specific preferences end public static function ShouldShowPopUp() { $today = mktime(0, 0, 0, gmdate('m'), gmdate('d'), gmdate('Y')); $remindDate = Application_Model_Preference::GetRemindMeDate(); $retVal = false; if (is_null($remindDate) || ($remindDate != -1 && $today >= $remindDate)) { $retVal = true; } return $retVal; } public static function getOrderingMap($pref_param) { $v = self::getValue($pref_param, true); $id = function ($x) { return $x; }; if ($v === '') { return $id; } $ds = unserialize($v); if (is_null($ds) || !is_array($ds)) { return $id; } if (!array_key_exists('ColReorder', $ds)) { return $id; } return function ($x) use ($ds) { if (array_key_exists($x, $ds['ColReorder'])) { return $ds['ColReorder'][$x]; } /*For now we just have this hack for debugging. We should not rely on this behaviour in case of failure*/ Logging::warn("Index {$x} does not exist preferences"); Logging::warn('Defaulting to identity and printing preferences'); Logging::warn($ds); return $x; }; } public static function getCurrentLibraryTableColumnMap() { return self::getOrderingMap('library_datatable'); } public static function setCurrentLibraryTableSetting($settings) { $data = serialize($settings); self::setValue('library_datatable', $data, true); } public static function getCurrentLibraryTableSetting() { $data = self::getValue('library_datatable', true); return ($data != '') ? unserialize($data) : null; } public static function setTimelineDatatableSetting($settings) { $data = serialize($settings); self::setValue('timeline_datatable', $data, true); } public static function getTimelineDatatableSetting() { $data = self::getValue('timeline_datatable', true); return ($data != '') ? unserialize($data) : null; } public static function setNowPlayingScreenSettings($settings) { $data = serialize($settings); self::setValue('nowplaying_screen', $data, true); } public static function getNowPlayingScreenSettings() { $data = self::getValue('nowplaying_screen', true); return ($data != '') ? unserialize($data) : null; } public static function setLibraryScreenSettings($settings) { $data = serialize($settings); self::setValue('library_screen', $data, true); } public static function getLibraryScreenSettings() { $data = self::getValue('library_screen', true); return ($data != '') ? unserialize($data) : null; } public static function SetEnableReplayGain($value) { self::setValue('enable_replay_gain', $value, false); } public static function GetEnableReplayGain() { return self::getValue('enable_replay_gain', false); } public static function getReplayGainModifier() { $rg_modifier = self::getValue('replay_gain_modifier'); if ($rg_modifier === '') { return '0'; } return $rg_modifier; } public static function setReplayGainModifier($rg_modifier) { self::setValue('replay_gain_modifier', $rg_modifier, false); } public static function SetHistoryItemTemplate($value) { self::setValue('history_item_template', $value); } public static function GetHistoryItemTemplate() { return self::getValue('history_item_template'); } public static function SetHistoryFileTemplate($value) { self::setValue('history_file_template', $value); } public static function GetHistoryFileTemplate() { return self::getValue('history_file_template'); } public static function getDiskUsage() { $val = self::getValue('disk_usage'); return (strlen($val) == 0) ? 0 : $val; } public static function setDiskUsage($value) { self::setValue('disk_usage', $value); } public static function updateDiskUsage($filesize) { $currentDiskUsage = self::getDiskUsage(); if (empty($currentDiskUsage)) { $currentDiskUsage = 0; } self::setDiskUsage($currentDiskUsage + $filesize); } public static function setTuneinEnabled($value) { self::setValue('tunein_enabled', $value); } public static function getTuneinEnabled() { return self::getValue('tunein_enabled'); } public static function setTuneinPartnerKey($value) { self::setValue('tunein_partner_key', $value); } public static function getTuneinPartnerKey() { return self::getValue('tunein_partner_key'); } public static function setTuneinPartnerId($value) { self::setValue('tunein_partner_id', $value); } public static function getTuneinPartnerId() { return self::getValue('tunein_partner_id'); } public static function setTuneinStationId($value) { self::setValue('tunein_station_id', $value); } public static function getTuneinStationId() { return self::getValue('tunein_station_id'); } public static function geLastTuneinMetadataUpdate() { return self::getValue('last_tunein_metadata_update'); } public static function setLastTuneinMetadataUpdate($value) { self::setValue('last_tunein_metadata_update', $value); } // TaskManager Lock Timestamp public static function getTaskManagerLock() { return self::getValue('task_manager_lock'); } public static function setTaskManagerLock($value) { self::setValue('task_manager_lock', $value); } // SAAS-876 - Toggle indicating whether user is using custom stream settings public static function getUsingCustomStreamSettings() { $val = self::getValue('using_custom_stream_settings'); return empty($val) ? false : $val; } public static function setUsingCustomStreamSettings($value) { self::setValue('using_custom_stream_settings', $value); } // SAAS-876 - Store the default Icecast password to restore when switching // back to Airtime Pro streaming settings public static function getRadioPageDisplayLoginButton() { return self::getValue('radio_page_display_login_button'); } public static function setRadioPageDisplayLoginButton($value) { self::setValue('radio_page_display_login_button', $value); } public static function getScheduleTrimOverbooked() { return boolval(self::getValue('schedule_trim_overbooked', false)); } public static function setScheduleTrimOverbooked($value) { self::setValue('schedule_trim_overbooked', $value); } public static function getRadioPageDisabled() { return boolval(self::getValue('radio_page_disabled', false)); } public static function setRadioPageDisabled($value) { self::setValue('radio_page_disabled', $value); } public static function getLangTimezoneSetupComplete() { return self::getValue('lang_tz_setup_complete'); } public static function setLangTimezoneSetupComplete($value) { self::setValue('lang_tz_setup_complete', $value); } public static function getWhatsNewDialogViewed() { $val = self::getValue('whats_new_dialog_viewed', true); if (empty($val)) { // Check the default (no user ID) value if the user value is empty // This is so that new stations won't see the popup $val = self::getValue('whats_new_dialog_viewed', false, true); } return empty($val) ? false : $val; } public static function setWhatsNewDialogViewed($value) { self::setValue('whats_new_dialog_viewed', $value, true); } public static function getAutoPlaylistPollLock() { return self::getValue('autoplaylist_poll_lock'); } public static function setAutoPlaylistPollLock($value) { self::setValue('autoplaylist_poll_lock', $value); } public static function getPodcastPollLock() { return self::getValue('podcast_poll_lock'); } public static function setPodcastPollLock($value) { self::setValue('podcast_poll_lock', $value); } public static function getStationPodcastId() { // Create the Station podcast if it doesn't exist. $stationPodcastId = self::getValue('station_podcast_id'); if (empty($stationPodcastId)) { $stationPodcastId = Application_Service_PodcastService::createStationPodcast(); } return $stationPodcastId; } public static function setStationPodcastId($value) { self::setValue('station_podcast_id', $value); } // SAAS-1081 - Implement a universal download key for downloading episodes from the station podcast // Store and increment the download counter, resetting every month public static function getStationPodcastDownloadKey() { return self::getValue('station_podcast_download_key'); } public static function setStationPodcastDownloadKey($value = null) { $value = empty($value) ? (new Application_Model_Auth())->generateRandomString() : $value; self::setValue('station_podcast_download_key', $value); } public static function getStationPodcastDownloadResetTimer() { return self::getValue('station_podcast_download_reset_timer'); } public static function setStationPodcastDownloadResetTimer($value) { self::setValue('station_podcast_download_reset_timer', $value); } public static function getStationPodcastDownloadCounter() { return self::getValue('station_podcast_download_counter'); } public static function resetStationPodcastDownloadCounter() { self::setValue('station_podcast_download_counter', 0); } public static function incrementStationPodcastDownloadCounter() { $c = self::getStationPodcastDownloadCounter(); self::setValue('station_podcast_download_counter', empty($c) ? 1 : ++$c); } // For fail cases, we may need to decrement the download counter public static function decrementStationPodcastDownloadCounter() { $c = self::getStationPodcastDownloadCounter(); self::setValue('station_podcast_download_counter', empty($c) ? 0 : --$c); } /** * @return int either 0 (public) or 1 (private) */ public static function getStationPodcastPrivacy() { return self::getValue('station_podcast_privacy'); } public static function setStationPodcastPrivacy($value) { self::setValue('station_podcast_privacy', $value); } /** * Getter for feature preview mode. * * @return bool */ public static function GetFeaturePreviewMode() { return self::getValue('feature_preview_mode') === '1'; } /** * Setter for feature preview mode. * * @param bool $value */ public static function SetFeaturePreviewMode($value) { return self::setValue('feature_preview_mode', $value); } /* * Stores liquidsoap status if $boot_time > save time. * save time is the time that user clicked save on stream setting page */ public static function setLiquidsoapError($stream_id, $msg, $boot_time = null) { $update_time = Application_Model_Preference::GetStreamUpdateTimestemp(); if ($boot_time == null || $boot_time > $update_time) { $stream_id = trim($stream_id, 's'); self::setValue("stream_liquidsoap_status:{$stream_id}", $msg); } } public static function getLiquidsoapError($stream_id) { $result = self::getValue("stream_liquidsoap_status:{$stream_id}"); return ($result !== false) ? $result : null; } public static function GetAllListenerStatErrors() { $sql = <<<'SQL' SELECT * FROM cc_pref WHERE keystr LIKE 'stream_stats_status:%' SQL; return Application_Common_Database::prepareAndExecute($sql, []); } public static function SetListenerStatError($stream_id, $value) { $stream_id = trim($stream_id, 's'); self::setValue("stream_stats_status:{$stream_id}", $value); } }