Beispiel #1
0
 /**
  * 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;
 }
Beispiel #2
0
 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;
 }
Beispiel #3
0
 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);
 }
Beispiel #4
0
 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;
 }
Beispiel #5
0
 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;
 }
Beispiel #6
0
 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;
 }
Beispiel #7
0
 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;
 }
Beispiel #8
0
 /**
  * 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;
 }
Beispiel #9
0
 /**
  * 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();
 }
Beispiel #10
0
 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'];
 }
Beispiel #11
0
 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;
     }
 }
Beispiel #12
0
 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;
 }
Beispiel #13
0
 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;
 }
Beispiel #14
0
 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;
 }
Beispiel #15
0
 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;
 }