/** * Static Functions */ public static function fetchFeatured() { $news = \DF\Cache::get('homepage_featured_news'); if (!$news) { $news = self::fetch(); \DF\Cache::save($news, 'homepage_featured_news', null, 300); } return $news; }
public static function generate() { set_time_limit(60); // Fix DF\URL // prefixing. \DF\Url::forceSchemePrefix(true); $nowplaying = self::loadNowPlaying(); // Post statistics to official record (legacy for duplication, for now) // Analytics::post($nowplaying['api']); // Post statistics to InfluxDB. $influx = self::getInflux(); $influx->setDatabase('pvlive_stations'); $active_shortcodes = Station::getShortNameLookup(); $total_overall = 0; foreach ($nowplaying['api'] as $short_code => $info) { $listeners = (int) $info['listeners']['current']; $station_id = $info['station']['id']; if (isset($active_shortcodes[$short_code])) { $total_overall += $listeners; } $influx->insert('station.' . $station_id . '.listeners', ['value' => $listeners]); } $influx->insert('all.listeners', ['value' => $total_overall]); // Clear any records that are not audio/video category. $api_categories = array('audio', 'video'); foreach ($nowplaying['api'] as $station_shortcode => $station_info) { if (!in_array($station_info['station']['category'], $api_categories)) { unset($nowplaying['api'][$station_shortcode]); unset($nowplaying['legacy'][$station_shortcode]); } } // Generate PVL legacy nowplaying file. $nowplaying_feed = json_encode($nowplaying['legacy'], JSON_UNESCAPED_SLASHES); $pvl_file_path = \PVL\Service\AmazonS3::path('api/nowplaying.json'); @file_put_contents($pvl_file_path, $nowplaying_feed); $legacy_file_path = DF_INCLUDE_STATIC . '/api/nowplaying.json'; @file_put_contents($legacy_file_path, $nowplaying_feed); // Generate PVL API cache. $np_api = $nowplaying['api']; foreach ($np_api as $station => $np_info) { $np_api[$station]['cache'] = 'hit'; } Cache::save($np_api, 'api_nowplaying_data', array('nowplaying'), 60); foreach ($np_api as $station => $np_info) { $np_api[$station]['cache'] = 'flatfile'; } // Generate PVL API nowplaying file. $file_path_api = \PVL\Service\AmazonS3::path('api/nowplaying_api.json'); $nowplaying_api = json_encode(array('status' => 'success', 'result' => $np_api), JSON_UNESCAPED_SLASHES); @file_put_contents($file_path_api, $nowplaying_api); // Push to live-update service. PvlNode::push('nowplaying', $nowplaying['api']); return $pvl_file_path; }
public function listAction() { $return = \DF\Cache::get('api_songs'); if (!$return) { ini_set('memory_limit', '-1'); $all_songs = Song::fetchArray(); $return = array(); foreach ($all_songs as $song) { $return[$song['id']] = Song::api($song); } \DF\Cache::save($return, 'api_songs', array(), 60); } return $this->returnSuccess($return); }
public static function getTypeTotals() { $totals = \DF\Cache::get('artist_totals'); if (!$totals) { $totals = array(); $records = self::fetchAll(); foreach ($records as $record) { $totals['types'][$record->id] = array('name' => $record->name, 'icon' => $record->icon, 'count' => count($record->artists)); } $totals['overall'] = array('count' => count(Artist::fetchArray())); \DF\Cache::save($totals, 'artist_totals', array(), 600); } return $totals; }
public function viewAction() { $id = (int) $this->getParam('id'); $record = Artist::find($id); if (!$record instanceof Artist) { throw new \DF\Exception\DisplayOnly('Artist Not Found'); } $this->view->artist = $record; // Generate statistics. $cache_key = 'artist_' . $record->id . '_stats'; $stats = \DF\Cache::get($cache_key); if (empty($stats)) { $stats = array('plays_per_day' => array(), 'song_lists' => array('most_played' => array('label' => 'Most Played Songs', 'songs' => array()), 'most_liked' => array('label' => 'Most Liked Songs', 'songs' => array()), 'most_recent' => array('label' => 'Most Recently Played', 'songs' => array()))); $active_streams = \Entity\StationStream::getMainRadioStreams(); $songs = $this->em->createQuery('SELECT s, sh FROM Entity\\Song s LEFT JOIN s.history sh WHERE s.artist LIKE :artist_q AND sh.stream_id IN (:streams) ORDER BY s.title, sh.timestamp DESC')->setParameter('artist_q', '%' . $record->name . '%')->setParameter('streams', $active_streams)->getArrayResult(); $plays_per_day = array(); foreach ($songs as &$song) { foreach ((array) $song['history'] as $i => $history) { // Get day of song play, incremenet counter. $day = strtotime(date('Y-m-d', $history['timestamp']) . ' 00:00:00') * 1000; $plays_per_day[$day] += 1; // Increment votes. $song['score_likes'] += $history['score_likes']; $song['score_dislikes'] += $history['score_dislikes']; } unset($song['history']); // Increment vote totals. $song['score_total'] = $song['score_likes'] - $song['score_dislikes']; $song['votes'] = $song['score_likes'] + $song['score_dislikes']; } // Remove current day, as it will always be lower. $current_day = strtotime(date('Y-m-d') . ' 00:00:00') * 1000; unset($plays_per_day[$current_day]); ksort($plays_per_day); foreach ($plays_per_day as $plays_day => $plays_total) { $stats['plays_per_day'][] = array($plays_day, $plays_total); } $stats['song_lists']['most_played']['songs'] = array_slice(Utilities::irsort($songs, 'play_count'), 0, 10); $stats['song_lists']['most_liked']['songs'] = array_slice(Utilities::irsort($songs, 'score_total'), 0, 10); $stats['song_lists']['most_recent']['songs'] = array_slice(Utilities::irsort($songs, 'last_played'), 0, 10); \DF\Cache::save($stats, $cache_key, array(), 300); } $this->view->stats = $stats; }
public static function getTotals() { $totals = \DF\Cache::get('archive_genre_totals'); if (!$totals) { $em = self::getEntityManager(); $conn = $em->getConnection(); $totals_raw = $conn->fetchAll('SELECT ag.id, ag.name, COUNT(ashg.song_id) AS songs FROM archive_genre AS ag LEFT JOIN archive_song_has_genre AS ashg ON ashg.genre_id = ag.id GROUP BY ag.id ORDER BY ag.name ASC'); $totals = array(); foreach ($totals_raw as $row) { $totals[$row['id']] = array('name' => $row['name'], 'total' => $row['songs']); } \DF\Cache::save($totals, 'archive_genre_totals', array(), 600); } return $totals; }
public static function fetchArray($cached = true) { static $settings; if (!$settings || !$cached) { $settings = \DF\Cache::get('all_settings'); if (!$settings || !$cached) { $em = self::getEntityManager(); $settings_raw = $em->createQuery('SELECT s FROM ' . __CLASS__ . ' s ORDER BY s.setting_key ASC')->getArrayResult(); $settings = array(); foreach ((array) $settings_raw as $setting) { $settings[$setting['setting_key']] = $setting['setting_value']; } \DF\Cache::save($settings, 'all_settings', array(), 8640); } } return $settings; }
/** * Static Functions */ public static function getAllConventions() { $all_cons = \DF\Cache::get('homepage_conventions'); if (!$all_cons) { $all_cons = array('upcoming' => self::getUpcomingConventions(), 'archived' => self::getConventionsWithArchives()); \DF\Cache::save($all_cons, 'homepage_conventions', array(), 1800); } return $all_cons; }
/** * Main display. */ public function indexAction() { // Inject all stations. $stations = \Entity\Station::fetchAll(); $this->view->stations = $stations; // Inject all podcasts. $podcasts = \Entity\Podcast::fetchAll(); $this->view->podcasts = $podcasts; // Pull cached statistic charts if available. $metrics = \DF\Cache::get('admin_metrics'); if (!$metrics) { // Statistics by day. $influx = $this->di->get('influx'); $station_averages = array(); $network_data = array('PVL Network' => array('ranges' => array(), 'averages' => array())); $daily_stats = $influx->setDatabase('pvlive_stations')->query('SELECT * FROM /1d.*/ WHERE time > now() - 180d', 'm'); foreach ($daily_stats as $stat_series => $stat_rows) { $series_split = explode('.', $stat_series); if ($series_split[1] == 'all') { $network_name = 'PVL Network'; foreach ($stat_rows as $stat_row) { $network_data[$network_name]['ranges'][$stat_row['time']] = array($stat_row['time'], $stat_row['min'], $stat_row['max']); $network_data[$network_name]['averages'][$stat_row['time']] = array($stat_row['time'], round($stat_row['value'], 2)); } } else { $station_id = $series_split[2]; foreach ($stat_rows as $stat_row) { $station_averages[$station_id][$stat_row['time']] = array($stat_row['time'], round($stat_row['value'], 2)); } } } $network_metrics = array(); foreach ($network_data as $network_name => $data_charts) { if (isset($data_charts['ranges'])) { $metric_row = new \stdClass(); $metric_row->name = $network_name . ' Listener Range'; $metric_row->type = 'arearange'; ksort($data_charts['ranges']); $metric_row->data = array_values($data_charts['ranges']); $network_metrics[] = $metric_row; } if (isset($data_charts['averages'])) { $metric_row = new \stdClass(); $metric_row->name = $network_name . ' Daily Average'; $metric_row->type = 'spline'; ksort($data_charts['averages']); $metric_row->data = array_values($data_charts['averages']); $network_metrics[] = $metric_row; } } $station_metrics = array(); foreach ($stations as $station) { $station_id = $station['id']; if (isset($station_averages[$station_id])) { $series_obj = new \stdClass(); $series_obj->name = $station['name']; $series_obj->type = 'spline'; ksort($station_averages[$station_id]); $series_obj->data = array_values($station_averages[$station_id]); $station_metrics[] = $series_obj; } } // Podcast and API Call Metrics $analytics_raw = $influx->setDatabase('pvlive_analytics')->query('SELECT * FROM /1h.*/', 'm'); $raw_metrics = array(); foreach ($analytics_raw as $series_name => $series_stats) { $series_parts = explode('.', $series_name); if ($series_parts[1] == 'api_calls') { $metric_section = 'api'; } else { $metric_section = 'podcast'; } foreach ($series_stats as $stat_row) { if (!isset($raw_metrics[$metric_section][$stat_row['time']])) { $raw_metrics[$metric_section][$stat_row['time']] = 0; } $raw_metrics[$metric_section][$stat_row['time']] += $stat_row['count']; } } // Reformat for highcharts. $refined_metrics = array(); foreach ($raw_metrics as $metric_type => $metric_rows) { ksort($metric_rows); foreach ($metric_rows as $row_timestamp => $row_value) { $refined_metrics[$metric_type][] = array($row_timestamp, $row_value); } } // API call object $series_obj = new \stdClass(); $series_obj->name = 'API Calls'; $series_obj->type = 'spline'; $series_obj->data = $refined_metrics['api']; $api_metrics = array($series_obj); // Podcast object $series_obj = new \stdClass(); $series_obj->name = 'Podcast Clicks'; $series_obj->type = 'spline'; $series_obj->data = $refined_metrics['podcast']; $podcast_metrics = array($series_obj); $metrics = array('network' => json_encode($network_metrics), 'station' => json_encode($station_metrics), 'api' => json_encode($api_metrics), 'podcast' => json_encode($podcast_metrics)); \DF\Cache::save($metrics, 'admin_metrics', array(), 600); } $this->view->metrics = $metrics; // Synchronization statuses if ($this->acl->isAllowed('administer all')) { $this->view->sync_times = \PVL\SyncManager::getSyncTimes(); } // PVLNode service stats. $this->view->pvlnode_stats = \PVL\Service\PvlNode::fetch(); }
protected function _initEvents() { $event_info = Cache::get('pvlive_events'); if (!$event_info) { $events_raw = $this->em->createQuery('SELECT s, st FROM Entity\\Schedule s JOIN s.station st WHERE (s.end_time >= :current AND s.start_time <= :future) ORDER BY s.start_time ASC')->setParameter('current', time())->setParameter('future', strtotime('+4 days'))->getArrayResult(); $all_events = array(); $events_by_day = array(); for ($i = 0; $i < 6; $i++) { $day_timestamp = mktime(0, 0, 1, date('n'), (int) date('j') + $i); $day_date = date('Y-m-d', $day_timestamp); $is_today = $day_date == date('Y-m-d'); $events_by_day[$day_date] = array('day_name' => $is_today ? 'Today' : date('l', $day_timestamp), 'timestamp' => $day_timestamp, 'is_today' => $is_today, 'events' => array()); } foreach ($events_raw as $event) { $event['image_url'] = \PVL\Url::upload(Schedule::getRowImageUrl($event)); $event['status'] = $event['start_time'] <= time() ? 'now' : 'upcoming'; $event['range'] = Schedule::getRangeText($event['start_time'], $event['end_time'], $event['is_all_day']); if ($event['station_id']) { $sid = $event['station_id']; if (isset($this->stations[$sid])) { $station = $this->stations[$sid]; unset($station['nowplaying_data'], $station['streams'], $station['intake_votes']); $event['station'] = $station; } } $all_events[] = $event; for ($i = $event['start_time']; $i <= $event['end_time']; $i += 86400) { $event_date = date('Y-m-d', $i); if (isset($events_by_day[$event_date])) { $events_by_day[$event_date]['events'][] = $event; } } } $event_info = array('all' => $all_events, 'by_day' => $events_by_day); Cache::save($event_info, 'pvlive_events', array(), 60); } $this->view->all_events = $event_info['all']; $this->view->events_by_day = $event_info['by_day']; }
public function indexAction() { // Get calendar name. $short_names = Station::getShortNameLookup(); $station_shortcode = $this->getParam('station', 'all'); if ($station_shortcode != "all") { $station = $short_names[$station_shortcode]; $calendar_name = $station['name']; } else { $calendar_name = 'Ponyville Live!'; } // Get timestamp boundaries. if ($this->hasParam('month')) { $show = $this->getParam('month'); $calendar = new \DF\Calendar($show); $timestamps = $calendar->getTimestamps(); $start_timestamp = $timestamps['start']; $end_timestamp = $timestamps['end']; $use_cache = true; $cache_name = 'month_' . $show; $calendar_name .= ' - ' . date('F Y', $timestamps['mid']); } elseif ($this->hasParam('start')) { $start_timestamp = (int) $this->getParam('start'); $end_timestamp = (int) $this->getParam('end'); $use_cache = false; $cache_name = null; // $cache_name = 'range_'.$start_timestamp.'_'.$end_timestamp; $calendar_name .= ' - ' . date('F j, Y', $start_timestamp) . ' to ' . date('F j, Y', $end_timestamp); } else { $start_timestamp = time(); $end_timestamp = time() + 86400 * 30; $use_cache = true; $cache_name = 'upcoming'; $calendar_name .= ' - Upcoming'; } // Load from cache or regenerate. if ($use_cache) { $cache_name = 'api_sched_' . $station_shortcode . '_' . $cache_name; $events = \DF\Cache::get($cache_name); } else { $events = null; } if (!$events) { if ($station_shortcode != "all") { $station = $short_names[$station_shortcode]; $events_raw = $this->em->createQuery('SELECT s FROM Entity\\Schedule s WHERE (s.station_id = :sid) AND (s.start_time <= :end AND s.end_time >= :start) ORDER BY s.start_time ASC')->setParameter('sid', $station['id'])->setParameter('start', $start_timestamp)->setParameter('end', $end_timestamp)->getArrayResult(); } else { $events_raw = $this->em->createQuery('SELECT s, st FROM Entity\\Schedule s LEFT JOIN s.station st WHERE (s.start_time <= :end AND s.end_time >= :start) ORDER BY s.start_time ASC')->setParameter('start', $start_timestamp)->setParameter('end', $end_timestamp)->getArrayResult(); } $events = array(); foreach ((array) $events_raw as $event) { $events[] = Schedule::api($event); } if ($use_cache) { \DF\Cache::save($events, $cache_name, array(), 300); } } $format = strtolower($this->getParam('format', 'json')); switch ($format) { case "ics": case "ical": return $this->_printCalendar($events, $calendar_name, $cache_name); break; case "json": default: return $this->returnSuccess($events); break; } }
public static function fetchArray($cached = true) { $podcasts = \DF\Cache::get('podcasts'); if (!$podcasts || !$cached) { $em = self::getEntityManager(); $podcasts = $em->createQuery('SELECT p FROM ' . __CLASS__ . ' p WHERE p.is_approved = 1 ORDER BY p.name ASC')->getArrayResult(); \DF\Cache::save($podcasts, 'podcasts', array(), 60); } return $podcasts; }
public function indexAction() { $influx = $this->di->get('influx'); $influx->setDatabase('pvlive_analytics'); set_time_limit(300); ini_set('memory_limit', '256M'); $stats = \DF\Cache::get('admin_api_calls'); if (!$stats) { $threshold = time() - 86400 * 2.5; $seconds_in_threshold = time() - $threshold; $minutes_in_threshold = round($seconds_in_threshold / 60); $stats = array('speed_by_function' => array(), 'calls_by_function' => array(), 'calls_by_client' => array(), 'calls_by_useragent' => array(), 'calls_by_ip' => array(), 'calls_by_hour' => array()); // Speed and Calls by Function try { $stats_by_func = $influx->query('SELECT count(value) AS total_calls, mean(requesttime) AS request_time, controller FROM api_calls GROUP BY controller', 's'); $stats_by_func = array_pop($stats_by_func); } catch (\Exception $e) { $stats_by_func = array(); } $total_calls = 0; foreach ($stats_by_func as $func_row) { $func = $func_row['controller']; $total_calls += $func_row['total_calls']; $stats['speed_by_function'][$func] = round($func_row['request_time'] * 1000, 2); $stats['calls_by_function'][$func] = $func_row['total_calls']; } // Calls per client try { $stats_by_client = $influx->query('SELECT count(value) AS num_calls, client FROM api_calls GROUP BY client'); $stats_by_client = array_pop($stats_by_client); } catch (\Exception $e) { $stats_by_client = array(); } foreach ($stats_by_client as $row) { $stats['calls_by_client'][$row['client']] = $row['num_calls']; } // Calls per user-agent try { $stats_by_ua = $influx->query('SELECT count(value) AS num_calls, useragent FROM api_calls GROUP BY useragent'); $stats_by_ua = array_pop($stats_by_ua); } catch (\Exception $e) { $stats_by_ua = array(); } foreach ($stats_by_ua as $row) { $stats['calls_by_useragent'][$row['useragent']] = $row['num_calls']; } // Calls per IP try { $stats_by_ip = $influx->query('SELECT count(value) AS num_calls, ip FROM api_calls GROUP BY ip'); $stats_by_ip = array_pop($stats_by_ip); } catch (\Exception $e) { $stats_by_ip = array(); } foreach ($stats_by_ip as $row) { $stats['calls_by_ip'][$row['ip']] = $row['num_calls']; } /* // Calls by hour */ foreach ($stats as $stat_category => &$stat_items) { arsort($stat_items); $stat_items = array_slice($stat_items, 0, 10); foreach ($stat_items as $stat_key => &$stat_value) { $stat_value = array('total' => $stat_value, 'percentage' => round($stat_value / $total_calls * 100, 2)); } } $stats['meta'] = array('threshold' => $threshold, 'total_calls' => $total_calls, 'calls_per_minute' => round($total_calls / $minutes_in_threshold, 3)); \DF\Cache::save($stats, 'admin_api_calls', array(), 300); } $this->view->statistics = $stats; }
protected function _getIgnoredSongs() { $song_hashes = \DF\Cache::get('station_center_ignored_songs'); if (!$song_hashes) { $ignored_phrases = array('Offline', 'Sweeper', 'Bumper', 'Unknown'); $qb = $this->em->createQueryBuilder(); $qb->select('s.id')->from('Entity\\Song', 's'); foreach ($ignored_phrases as $i => $phrase) { $qb->orWhere('s.text LIKE ?' . ($i + 1)); $qb->setParameter($i + 1, '%' . $phrase . '%'); } $song_hashes_raw = $qb->getQuery()->getArrayResult(); $song_hashes = array(); foreach ($song_hashes_raw as $row) { $song_hashes[$row['id']] = $row['id']; } \DF\Cache::save($song_hashes, 'station_center_ignored_songs', array(), 86400); } return $song_hashes; }
public static function fetchArray($cached = true) { $stations = \DF\Cache::get('stations'); if (!$stations || !$cached) { $em = self::getEntityManager(); $stations = $em->createQuery('SELECT s, ss FROM ' . __CLASS__ . ' s LEFT JOIN s.streams ss WHERE s.is_active = 1 AND s.category IN (:types) ORDER BY s.category ASC, s.weight ASC')->setParameter('types', array('audio', 'video'))->getArrayResult(); foreach ($stations as &$station) { $station['short_name'] = self::getStationShortName($station['name']); foreach ((array) $station['streams'] as $stream) { if ($stream['is_default']) { $station['default_stream_id'] = $stream['id']; $station['stream_url'] = $stream['stream_url']; } } } \DF\Cache::save($stations, 'stations', array(), 60); } return $stations; }