/** * The UI to show OCF demographics. * * @param object The stats module object * @param string The screen type * @return tempcode The UI */ function demographics($ob, $type) { breadcrumb_set_parents(array(array('_SELF:_SELF:misc', do_lang_tempcode('SITE_STATISTICS')))); require_lang('ocf'); //This will show a plain bar chart with all the downloads listed $title = get_page_title('DEMOGRAPHICS'); // Handle time range if (get_param_integer('dated', 0) == 0) { $title = get_page_title('DEMOGRAPHICS'); return $ob->get_between($title, false, NULL, do_lang_tempcode('DEMOGRAPHICS_STATS_RANGE')); } $time_start = get_input_date('time_start', true); $time_end = get_input_date('time_end', true); if (!is_null($time_end)) { $time_end += 60 * 60 * 24 - 1; } // So it is end of day not start if (is_null($time_start) && is_null($time_end)) { $rows = $GLOBALS['FORUM_DB']->query_select('f_members', array('m_dob_year', 'COUNT(*) AS cnt', NULL, 'GROUP BY m_dob_year')); } else { if (is_null($time_start)) { $time_start = 0; } if (is_null($time_end)) { $time_end = time(); } $title = get_page_title('SECTION_DEMOGRAPHICS_RANGE', true, array(escape_html(get_timezoned_date($time_start, false)), escape_html(get_timezoned_date($time_end, false)))); $rows = $GLOBALS['FORUM_DB']->query('SELECT m_dob_year,COUNT(*) AS cnt FROM ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_members WHERE m_join_time>' . strval($time_start) . ' AND m_join_time<' . strval($time_end) . ' GROUP BY m_dob_year'); } if (count($rows) < 1) { return warn_screen($title, do_lang_tempcode('NO_DATA')); } // Gather data $demographics = array(); $demographics[do_lang('UNKNOWN')] = 0; for ($i = 0; $i < 30; $i++) { $demographics[strval($i)] = 0; } for ($i = 30; $i < 100; $i += 5) { $demographics[strval($i) . '-' . strval($i + 4)] = 0; } $demographics['100+'] = 0; list($current_day, $current_month, $current_year) = explode(' ', date('j m Y', utctime_to_usertime(time()))); foreach ($rows as $i => $row) { $day = 1; $month = 1; $year = $row['m_dob_year']; if (!is_null($year)) { $age = intval($current_year) - $year; if ($age < 0) { $age = 0; } if ($age >= 100) { $age_string = '100+'; } elseif ($age >= 30) { $age_string = strval(intval($age / 5) * 5) . '-' . strval(intval($age / 5) * 5 + 4); } else { $age_string = strval($age); } $demographics[$age_string] += array_key_exists('cnt', $row) ? $row['cnt'] : 1; } else { $demographics[do_lang('UNKNOWN')] += array_key_exists('cnt', $row) ? $row['cnt'] : 1; } } $start = 0; $max = 1000; // Little trick, as we want all to fit $sortables = array(); require_code('templates_results_table'); $fields_title = results_field_title(array(do_lang_tempcode('AGE'), do_lang_tempcode('COUNT_TOTAL')), $sortables); $fields = new ocp_tempcode(); $i = 0; foreach ($demographics as $_age => $value) { if (is_integer($_age)) { $_age = strval($_age); } $percent = round(100.0 * floatval($value) / floatval(count($rows)), 2); $fields->attach(results_entry(array(escape_html($_age), escape_html(integer_format($value) . ' (' . float_format($percent) . '%)')))); $i++; } $list = results_table(do_lang_tempcode('DEMOGRAPHICS'), $start, 'start', $max, 'max', count($demographics), $fields_title, $fields, $sortables, '', '', 'sort', new ocp_tempcode()); $output = create_bar_chart($demographics, do_lang('AGE'), do_lang('COUNT_TOTAL'), '', ''); $ob->save_graph('Global-Demographics', $output); $graph = do_template('STATS_GRAPH', array('GRAPH' => get_custom_base_url() . '/data_custom/modules/admin_stats/Global-Demographics.xml', 'TITLE' => do_lang_tempcode('DEMOGRAPHICS'), 'TEXT' => do_lang_tempcode('DESCRIPTION_DEMOGRAPHICS'))); return do_template('STATS_SCREEN', array('TITLE' => $title, 'NO_CSV' => '1', 'GRAPH' => $graph, 'STATS' => $list)); }
/** * Create a bar chart of the views the specified page has received in relation to the specified hours. The bar chart is stored in /data_custom/admin_stats/ as an SVG image, and the tempcode for display of the graph and results table is returned. * * @param PATH The page path * @param string The statistic type (for use in sort parameters and such) * @param string Language identifier for the graph title * @param string Language identifier for the graph description * @param integer The steps of hours to use * @param integer The total hours to plot * @return array A linear array containing the graph and list tempcode objects, respectively */ function views_per_x($page, $type, $graph_title, $graph_description, $hours = 1, $total = 24) { //Return a graph with the views per hour for a specified page $start = get_param_integer('start_' . $type, 0); $max = get_param_integer('max_' . $type, 50); $sortables = array('date_and_time' => do_lang_tempcode('DATE_TIME')); $test = explode(' ', get_param('sort', 'date_and_time ASC'), 2); if (count($test) == 1) { $test[1] = 'DESC'; } list($sortable, $sort_order) = $test; if (strtoupper($sort_order) != 'ASC' && strtoupper($sort_order) != 'DESC' || !array_key_exists($sortable, $sortables)) { log_hack_attack_and_exit('ORDERBY_HACK'); } global $NON_CANONICAL_PARAMS; $NON_CANONICAL_PARAMS[] = 'sort'; $where = db_string_equal_to('the_page', $page); if (substr($page, 0, 6) == 'pages/') { $where .= ' OR ' . db_string_equal_to('the_page', '/' . $page); } // Legacy compatibility $ip_filter = $GLOBALS['DEBUG_MODE'] ? '' : ' AND ' . db_string_not_equal_to('ip', get_ip_address()); $query = 'SELECT id,date_and_time FROM ' . get_table_prefix() . 'stats WHERE (' . $where . ')' . $ip_filter . ' AND date_and_time>' . strval(time() - $total * 60 * 60) . ' AND date_and_time<=' . strval(time()) . ' ORDER BY ' . $sortable . ' ' . $sort_order; $rows = $GLOBALS['SITE_DB']->query($query, 5000); if (count($rows) < 1 || count($rows) == 5000) { $list = new ocp_tempcode(); $graph = new ocp_tempcode(); return array($graph, $list); } require_code('templates_results_table'); $fields_title = results_field_title(array(do_lang_tempcode('DATE_TIME'), do_lang_tempcode('COUNT_VIEWS')), $sortables, 'sort', $sortable . ' ' . $sort_order); $fields = new ocp_tempcode(); $data = array(); $round = 60 * 60 * $hours; $start_date_and_time = time() + $round - (time() + $round) % $round - $total * 60 * 60; $i = 0; for ($a = 0; $a < intval($total / $hours); $a++) { if ($i < $start) { $i++; continue; } elseif ($i >= $start + $max) { break; } $date = get_timezoned_date($start_date_and_time + $a * $hours * 60 * 60, $hours < 24); $to_date = get_timezoned_date($start_date_and_time + ($a + 1) * $hours * 60 * 60, $hours < 24); $data[$date] = 0; foreach ($rows as $value) { if ($value['date_and_time'] >= $start_date_and_time + $a * $hours * 60 * 60 && $value['date_and_time'] < $start_date_and_time + ($a + 1) * $hours * 60 * 60) { $data[$date]++; } elseif ($value['date_and_time'] > $start_date_and_time + ($a + 1) * $hours * 60 * 60) { break; } } $i++; $fields->attach(results_entry(array($date . ' - ' . $to_date, integer_format($data[$date])), true)); } $list = results_table(do_lang_tempcode('PAGES_STATISTICS', escape_html($page)), $start, 'start_' . $type, $max, 'max_' . $type, $i, $fields_title, $fields, $sortables, $sortable, $sort_order, 'sort_' . $type); $output = create_bar_chart($data, do_lang('DATE_TIME'), do_lang('COUNT_VIEWS'), '', ''); $this->save_graph(strval($rows[0]['id']) . '-Views-' . strval((int) $hours) . '_' . strval((int) $start_date_and_time), $output); $graph = do_template('STATS_GRAPH', array('GRAPH' => get_custom_base_url() . '/data_custom/modules/admin_stats/' . strval($rows[0]['id']) . '-Views-' . strval((int) $hours) . '_' . strval((int) $start_date_and_time) . '.xml', 'TITLE' => do_lang_tempcode($graph_title), 'TEXT' => do_lang_tempcode($graph_description))); return array($graph, $list); }
/** * The UI to show download statistics. * * @param object The stats module object * @param string The screen type * @return tempcode The UI */ function downloads($ob, $type) { breadcrumb_set_parents(array(array('_SELF:_SELF:misc', do_lang_tempcode('SITE_STATISTICS')))); require_lang('downloads'); //This will show a plain bar chart with all the downloads listed $title = get_page_title('SECTION_DOWNLOADS'); // Handle time range if (get_param_integer('dated', 0) == 0) { $title = get_page_title('SECTION_DOWNLOADS'); return $ob->get_between($title, false, NULL, do_lang_tempcode('DOWNLOAD_STATS_RANGE')); } $time_start = get_input_date('time_start', true); $time_end = get_input_date('time_end', true); if (!is_null($time_end)) { $time_end += 60 * 60 * 24 - 1; } // So it is end of day not start if (is_null($time_start) && is_null($time_end)) { $rows = $GLOBALS['SITE_DB']->query_select('download_downloads', array('id', 'num_downloads', 'name')); } else { if (is_null($time_start)) { $time_start = 0; } if (is_null($time_end)) { $time_end = time(); } $title = get_page_title('SECTION_DOWNLOADS_RANGE', true, array(escape_html(get_timezoned_date($time_start, false)), escape_html(get_timezoned_date($time_end, false)))); $rows = $GLOBALS['SITE_DB']->query('SELECT id,num_downloads,name FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'download_downloads WHERE add_date>' . strval($time_start) . ' AND add_date<' . strval($time_end)); } //$rows=array(array('id'=>1,'num_downloads'=>10,'name'=>3),array('id'=>2,'num_downloads'=>20,'name'=>4)); if (count($rows) < 1) { return warn_screen($title, do_lang_tempcode('NO_DATA')); } $downloads = array(); foreach ($rows as $i => $row) { if (!array_key_exists('num_downloads', $row)) { $row['num_downloads'] = $GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT COUNT(*) FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'download_logging WHERE id=' . strval($row['id'])); $rows[$i] = $row; } $downloads[get_translated_text($row['name']) . ' (#' . strval($row['id']) . ')'] = $row['num_downloads']; } $start = get_param_integer('start', 0); $max = get_param_integer('max', 30); $csv = get_param_integer('csv', 0) == 1; if ($csv) { if (function_exists('set_time_limit')) { @set_time_limit(0); } $start = 0; $max = 10000; } $sortables = array('num_downloads' => do_lang_tempcode('COUNT_DOWNLOADS')); $test = explode(' ', get_param('sort', 'num_downloads DESC'), 2); if (count($test) == 1) { $test[1] = 'DESC'; } list($sortable, $sort_order) = $test; if (strtoupper($sort_order) != 'ASC' && strtoupper($sort_order) != 'DESC' || !array_key_exists($sortable, $sortables)) { log_hack_attack_and_exit('ORDERBY_HACK'); } global $NON_CANONICAL_PARAMS; $NON_CANONICAL_PARAMS[] = 'sort'; if ($sort_order == 'ASC') { asort($downloads); } else { arsort($downloads); } require_code('templates_results_table'); $fields_title = results_field_title(array(do_lang_tempcode('TITLE'), do_lang_tempcode('COUNT_DOWNLOADS')), $sortables, 'sort', $sortable . ' ' . $sort_order); $fields = new ocp_tempcode(); $real_data = array(); $i = 0; foreach ($downloads as $download_name => $value) { if ($i < $start) { $i++; continue; } elseif ($i >= $start + $max) { break; } $fields->attach(results_entry(array(escape_html($download_name), escape_html(integer_format($value))))); $real_data[] = array('Download name' => $download_name, 'Tally' => $value); $i++; } $list = results_table(do_lang_tempcode('SECTION_DOWNLOADS'), $start, 'start', $max, 'max', count($downloads), $fields_title, $fields, $sortables, $sortable, $sort_order, 'sort', new ocp_tempcode()); if ($csv) { make_csv($real_data, 'download_stats.csv'); } $output = create_bar_chart(array_slice($downloads, $start, $max), do_lang('TITLE'), do_lang('COUNT_DOWNLOADS'), '', ''); $ob->save_graph('Global-Downloads', $output); $graph = do_template('STATS_GRAPH', array('GRAPH' => get_custom_base_url() . '/data_custom/modules/admin_stats/Global-Downloads.xml', 'TITLE' => do_lang_tempcode('SECTION_DOWNLOADS'), 'TEXT' => do_lang_tempcode('DESCRIPTION_DOWNLOADS_STATISTICS'))); return do_template('STATS_SCREEN', array('_GUID' => '4b8e0478231473d690e947ffc4580840', 'TITLE' => $title, 'GRAPH' => $graph, 'STATS' => $list)); }
/** * The UI to show OCF posting rates. * * @param object The stats module object * @param string The screen type * @return tempcode The UI */ function posting_rates($ob, $type) { breadcrumb_set_parents(array(array('_SELF:_SELF:misc', do_lang_tempcode('SITE_STATISTICS')))); require_lang('ocf'); //This will show a plain bar chart with all the downloads listed $title = get_page_title('POSTING_RATES'); // Handle time range if (get_param_integer('dated', 0) == 0) { $title = get_page_title('POSTING_RATES'); $extra_fields = new ocp_tempcode(); require_code('form_templates'); $extra_fields->attach(form_input_tick(do_lang_tempcode('HOURLY_BREAKDOWNS'), do_lang_tempcode('DESCRIPTION_HOURLY_BREAKDOWNS'), 'hourly', false)); return $ob->get_between($title, false, $extra_fields); } $time_start = get_input_date('time_start', true); $time_end = get_input_date('time_end', true); if (!is_null($time_end)) { $time_end += 60 * 60 * 24 - 1; } // So it is end of day not start if (is_null($time_start)) { $time_start = 0; } if (is_null($time_end)) { $time_end = time(); } $title = get_page_title('SECTION_POSTING_RATES_RANGE', true, array(escape_html(get_timezoned_date($time_start, false)), escape_html(get_timezoned_date($time_end, false)))); $poster_exception = ''; foreach (explode(',', get_param('poster_exception', '')) as $e) { if (trim($e) == '') { continue; } $poster_exception .= 'p_poster<>' . strval(intval($e)) . ' AND '; } $csv = get_param_integer('csv', 0) == 1; if ($csv) { $time_start = 0; $time_end = time(); $hourly = false; } $rows = $GLOBALS['FORUM_DB']->query('SELECT p_time FROM ' . $GLOBALS['FORUM_DB']->get_table_prefix() . 'f_posts WHERE ' . $poster_exception . 'p_time>' . strval($time_start) . ' AND p_time<' . strval($time_end)); if (count($rows) < 1) { return warn_screen($title, do_lang_tempcode('NO_DATA')); } $hourly = get_param_integer('hourly', 0) == 1; //($time_end-$time_start)<=60*60*24*2; $iterate_months = floatval($time_end - $time_start) / (60.0 * 60.0 * 24.0) > 100.0; // Gather data $posting_rates = array(); if ($hourly) { for ($i = 0; $i < 24; $i++) { $date = str_pad(strval($i), 2, '0', STR_PAD_LEFT) . ':00'; $posting_rates[$date] = 0; } } else { if ($iterate_months) { $year = intval(date('Y', $time_start)); $month = intval(date('m', $time_start)); while (mktime(0, 0, 0, $month - 1, 0, $year) < $time_end) { $date = date('Y/m', mktime(0, 0, 0, $month, 0, $year)); $posting_rates[$date] = 0; $month++; if ($month == 13) { $month = 1; $year++; } } } else { for ($i = $time_start - 60 * 60 * 12; $i <= $time_end + 60 * 60 * 12; $i += 60 * 60 * 24) { $date = date('Y/m/d', $i); $posting_rates[$date] = 0; } } } foreach ($rows as $row) { if ($hourly) { $date = date('H', $row['p_time']) . ':00'; } else { if ($iterate_months) { $date = date('Y/m', $row['p_time']); } else { $date = date('Y/m/d', $row['p_time']); } } $posting_rates[$date]++; } $start = 0; $max = 1000; // Little trick, as we want all to fit $sortables = array(); require_code('templates_results_table'); $fields_title = results_field_title(array(do_lang_tempcode('DATE'), do_lang_tempcode('COUNT_TOTAL')), $sortables); $fields = new ocp_tempcode(); $real_data = array(); $i = 0; foreach ($posting_rates as $date => $value) { $fields->attach(results_entry(array(escape_html($date), escape_html(integer_format($value))))); $real_data[] = array('Date/Time' => $date, 'Tally' => $value); $i++; } $list = results_table(do_lang_tempcode('POSTING_RATES'), $start, 'start', $max, 'max', count($posting_rates), $fields_title, $fields, $sortables, '', '', 'sort', new ocp_tempcode()); if ($csv) { make_csv($real_data, 'posting_rates.csv'); } $output = create_bar_chart($posting_rates, do_lang('DATE'), do_lang('COUNT_TOTAL'), '', ''); $ob->save_graph('Global-Posting_rates', $output); $graph = do_template('STATS_GRAPH', array('GRAPH' => get_custom_base_url() . '/data_custom/modules/admin_stats/Global-Posting_rates.xml', 'TITLE' => do_lang_tempcode('POSTING_RATES'), 'TEXT' => do_lang_tempcode('DESCRIPTION_POSTING_RATES'))); return do_template('STATS_SCREEN', array('TITLE' => $title, 'GRAPH' => $graph, 'STATS' => $list)); }