PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/application/models/stats.php

https://github.com/error10/Ushahidi_Web
PHP | 421 lines | 276 code | 81 blank | 64 comment | 40 complexity | ec132a5dae717c2c091cc260abdc3418 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Model for Statistics
  4. *
  5. *
  6. * PHP version 5
  7. * LICENSE: This source file is subject to LGPL license
  8. * that is available through the world-wide-web at the following URI:
  9. * http://www.gnu.org/copyleft/lesser.html
  10. * @author Ushahidi Team <team@ushahidi.com>
  11. * @package Ushahidi - http://source.ushahididev.com
  12. * @module Incident Model
  13. * @copyright Ushahidi - http://www.ushahidi.com
  14. * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License (LGPL)
  15. */
  16. class Stats_Model extends ORM
  17. {
  18. /*
  19. *
  20. *
  21. */
  22. static function get_javascript()
  23. {
  24. // Make sure cURL is installed
  25. if (!function_exists('curl_exec')) {
  26. throw new Kohana_Exception('footer.cURL_not_installed');
  27. return false;
  28. }
  29. $settings = ORM::factory('settings', 1);
  30. $stat_id = $settings->stat_id;
  31. if($stat_id == 0) return '';
  32. $url = 'http://tracker.ushahidi.com/px.php?task=tc&siteid='.$stat_id;
  33. $curl_handle = curl_init();
  34. curl_setopt($curl_handle,CURLOPT_URL,$url);
  35. curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,15); // Timeout set to 15 seconds. This is somewhat arbitrary and can be changed.
  36. curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1); // Set cURL to store data in variable instead of print
  37. $buffer = curl_exec($curl_handle);
  38. curl_close($curl_handle);
  39. try {
  40. $tag = @simplexml_load_string($buffer); // This works because the tracking code is only wrapped in one tag
  41. } catch (Exception $e) {
  42. // In case the xml was malformed for whatever reason, we will just guess what the tag should be here
  43. $tag = '<!-- Piwik -->
  44. <script type="text/javascript">
  45. var pkBaseURL = (("https:" == document.location.protocol) ? "https://tracker.ushahidi.com/piwik/" : "http://tracker.ushahidi.com/piwik/");
  46. document.write(unescape("%3Cscript src=\'" + pkBaseURL + "piwik.js\' type=\'text/javascript\'%3E%3C/script%3E"));
  47. </script><script type="text/javascript">
  48. try {
  49. var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", '.$stat_id.');
  50. piwikTracker.trackPageView();
  51. piwikTracker.enableLinkTracking();
  52. } catch( err ) {}
  53. </script><noscript><p><img src="http://tracker.ushahidi.com/piwik/piwik.php?idsite='.$stat_id.'" style="border:0" alt=""/></p></noscript>
  54. <!-- End Piwik Tag -->
  55. ';
  56. }
  57. return $tag;
  58. }
  59. /*
  60. * range will be ignored if dp1 and dp2 are set
  61. * dp1 and dp2 format is YYYY-MM-DD
  62. */
  63. static function get_hit_stats($range=30,$dp1=null,$dp2=null)
  64. {
  65. // Get ID for stats
  66. $settings = ORM::factory('settings', 1);
  67. $stat_id = $settings->stat_id;
  68. $twodates = '';
  69. if ($dp1 !== null AND $dp2 !== null) {
  70. $twodates = '&twodates='.urlencode($dp1.','.$dp2);
  71. }
  72. $stat_url = 'http://tracker.ushahidi.com/px.php?stat_key='.$settings->stat_key.'&task=stats&siteid='.urlencode($stat_id).'&period=day&range='.urlencode($range).$twodates;
  73. // Ignore errors since we are error checking later
  74. $response = @simplexml_load_string(self::_curl_req($stat_url));
  75. // If we encounter an error, return false
  76. if (isset($response->result->error[0]) OR isset($response->error[0]) OR ! isset($response->visits->result)) {
  77. Kohana::log('error', "Error on stats request");
  78. return false;
  79. }
  80. foreach ($response->visits->result as $res) {
  81. $dt = $res['date'];
  82. $y = substr($dt,0,4);
  83. $m = substr($dt,5,2);
  84. $d = substr($dt,8,2);
  85. $timestamp = mktime(0,0,0,$m,$d,$y)*1000;
  86. if (isset($res->nb_visits)){
  87. $data['visits'][ (string) $timestamp] = (string) $res->nb_visits;
  88. }else{
  89. $data['visits'][ (string) $timestamp] = '0';
  90. }
  91. if (isset($res->nb_uniq_visitors)){
  92. $data['uniques'][ (string) $timestamp] = (string) $res->nb_uniq_visitors;
  93. }else{
  94. $data['uniques'][ (string) $timestamp] = '0';
  95. }
  96. if (isset($res->nb_actions)){
  97. $data['pageviews'][ (string) $timestamp] = (string) $res->nb_actions;
  98. }else{
  99. $data['pageviews'][ (string) $timestamp] = '0';
  100. }
  101. }
  102. return $data;
  103. }
  104. static function get_hit_countries($range=30,$dp1=null,$dp2=null)
  105. {
  106. $settings = ORM::factory('settings', 1);
  107. $stat_id = $settings->stat_id;
  108. $twodates = '';
  109. if ($dp1 !== null AND $dp2 !== null) {
  110. $twodates = '&twodates='.urlencode($dp1.','.$dp2);
  111. }
  112. $stat_url = 'http://tracker.ushahidi.com/px.php?stat_key='.$settings->stat_key.'&task=stats&siteid='.urlencode($stat_id).'&period=day&range='.urlencode($range).$twodates;
  113. // Ignore errors since we are error checking later
  114. $response = @simplexml_load_string(self::_curl_req($stat_url));
  115. // If we encounter an error, return false
  116. if (isset($response->result->error[0]) OR isset($response->error[0]) OR ! isset($response->countries->result)) {
  117. Kohana::log('error', "Error on stats request");
  118. return false;
  119. }
  120. $data = array();
  121. foreach ($response->countries->result as $res) {
  122. $date = (string) $res['date'];
  123. foreach ($res->row as $row){
  124. $code = (string) $row->code;
  125. $data[$date][$code]['label'] = (string) $row->label;
  126. $data[$date][$code]['uniques'] = (string) $row->nb_uniq_visitors;
  127. $logo = (string) $row->logo;
  128. $data[$date][$code]['logo'] = 'http://tracker.ushahidi.com/piwik/'.$logo;
  129. }
  130. }
  131. return $data;
  132. }
  133. /*
  134. * get an array of report counts
  135. * @param approved - Only count approved reports if true
  136. * @param by_time - Format array with timestamp as the key if true
  137. * @param range - Number of days back from today to pull reports from. Will end up defaulting to 100000 days to get them all.
  138. * @param dp1 - Arbitrary date range. Low date. YYYY-MM-DD
  139. * @param dp2 - Arbitrary date range. High date. YYYY-MM-DD
  140. */
  141. static function get_report_stats($approved=false,$by_time=false,$range=null,$dp1=null,$dp2=null,$line_chart_data=false)
  142. {
  143. if ($range === null) {
  144. $range = 100000;
  145. }
  146. if ($dp1 === null) {
  147. $dp1 = 0;
  148. }
  149. if ($dp2 === null) {
  150. $dp2 = '3000-01-01';
  151. }
  152. // Set up the range calculation
  153. $time = time() - ($range*86400);
  154. $range_date = date('Y-m-d',$time);
  155. // Only grab approved
  156. if ($approved) {
  157. $reports = ORM::factory('incident')->where('incident_active','1')->where('incident_date >=',$dp1)->where('incident_date <=',$dp2)->where('incident_date >',$range_date)->find_all();
  158. }else{
  159. $reports = ORM::factory('incident')->where('incident_date >=',$dp1)->where('incident_date <=',$dp2)->where('incident_date >',$range_date)->find_all();
  160. }
  161. $reports_categories = ORM::factory('incident_category')->find_all();
  162. // Initialize arrays so we don't error out
  163. $report_data = array();
  164. $verified_counts = array();
  165. $approved_counts = array();
  166. $all = array();
  167. $earliest_timestamp = 32503680000; // Year 3000 in epoch so we can catch everything less than this.
  168. $latest_timestamp = 0;
  169. // Gather some data into an array on incident reports
  170. $num_reports = 0;
  171. foreach ($reports as $report) {
  172. $timestamp = (string) strtotime(substr($report->incident_date,0,10));
  173. $report_data[$report->id] = array(
  174. 'date'=>$timestamp,
  175. 'mode'=>$report->incident_mode,
  176. 'active'=>$report->incident_active,
  177. 'verified'=>$report->incident_verified
  178. );
  179. if ($timestamp < $earliest_timestamp) {
  180. $earliest_timestamp = $timestamp;
  181. }
  182. if ($timestamp > $latest_timestamp) {
  183. $latest_timestamp = $timestamp;
  184. }
  185. if ( ! isset($verified_counts['verified'][$timestamp])) {
  186. $verified_counts['verified'][$timestamp] = 0;
  187. $verified_counts['unverified'][$timestamp] = 0;
  188. $approved_counts['approved'][$timestamp] = 0;
  189. $approved_counts['unapproved'][$timestamp] = 0;
  190. $all[$timestamp] = 0;
  191. }
  192. $all[$timestamp]++;
  193. if ($report->incident_verified == 1){
  194. $verified_counts['verified'][$timestamp]++;
  195. }else{
  196. $verified_counts['unverified'][$timestamp]++;
  197. }
  198. if ($report->incident_active == 1){
  199. $approved_counts['approved'][$timestamp]++;
  200. }else{
  201. $approved_counts['unapproved'][$timestamp]++;
  202. }
  203. $num_reports++;
  204. }
  205. $category_counts = array();
  206. $lowest_date = 9999999999; // Really far in the future.
  207. $highest_date = 0;
  208. foreach ($reports_categories as $report){
  209. // if this report category doesn't have any reports (in case we are only
  210. // looking at approved reports), move on to the next one.
  211. if ( ! isset($report_data[$report->incident_id])) continue;
  212. $c_id = $report->category_id;
  213. $timestamp = $report_data[$report->incident_id]['date'];
  214. if ($timestamp < $lowest_date) {
  215. $lowest_date = $timestamp;
  216. }
  217. if ($timestamp > $highest_date) {
  218. $highest_date = $timestamp;
  219. }
  220. if ( ! isset($category_counts[$c_id][$timestamp])) {
  221. $category_counts[$c_id][$timestamp] = 0;
  222. }
  223. $category_counts[$c_id][$timestamp]++;
  224. }
  225. // Populate date range
  226. $date_range = array();
  227. $add_date = $lowest_date;
  228. while ($add_date <= $highest_date){
  229. $date_range[] = $add_date;
  230. $add_date += 86400;
  231. }
  232. // Zero out days that don't have a count
  233. foreach ($category_counts as & $arr) {
  234. foreach ($date_range as $timestamp){
  235. if ( ! isset($arr[$timestamp])) {
  236. $arr[$timestamp] = 0;
  237. }
  238. if ( ! isset($verified_counts['verified'][$timestamp])) {
  239. $verified_counts['verified'][$timestamp] = 0;
  240. }
  241. if ( ! isset($verified_counts['unverified'][$timestamp])) {
  242. $verified_counts['unverified'][$timestamp] = 0;
  243. }
  244. if ( ! isset($approved_counts['approved'][$timestamp])) {
  245. $approved_counts['approved'][$timestamp] = 0;
  246. }
  247. if ( ! isset($approved_counts['unapproved'][$timestamp])) {
  248. $approved_counts['unapproved'][$timestamp] = 0;
  249. }
  250. if ( ! isset($all[$timestamp])) {
  251. $all[$timestamp] = 0;
  252. }
  253. }
  254. // keep dates in order
  255. ksort($arr);
  256. ksort($verified_counts['verified']);
  257. ksort($verified_counts['unverified']);
  258. ksort($approved_counts['approved']);
  259. ksort($approved_counts['unapproved']);
  260. ksort($all);
  261. }
  262. // Add all our data sets to the array we are returning
  263. $data['category_counts'] = $category_counts;
  264. $data['verified_counts'] = $verified_counts;
  265. $data['approved_counts'] = $approved_counts;
  266. $data['all']['all'] = $all;
  267. // I'm just tacking this on here. However, we could improve performance
  268. // by implementing the code above but I just don't have the time
  269. // to mess with it.
  270. if ($by_time){
  271. // Reorder the array. Is there a built in PHP function that can do this?
  272. $new_data = array();
  273. foreach ($data as $main_key => $data_array){
  274. foreach ($data_array as $key => $counts){
  275. if ($line_chart_data == false){
  276. foreach ($counts as $timestamp => $count) $new_data[$main_key][$timestamp][$key] = $count;
  277. }else{
  278. foreach ($counts as $timestamp => $count){
  279. $timestamp_key = (string) ($timestamp*1000);
  280. if ( ! isset($new_data[$main_key][$timestamp_key])) {
  281. $new_data[$main_key][$timestamp_key] = 0;
  282. }
  283. $new_data[$main_key][$timestamp_key] += $count;
  284. }
  285. }
  286. }
  287. }
  288. $data = $new_data;
  289. }
  290. if ($line_chart_data == false) {
  291. $data['total_reports'] = $num_reports;
  292. $data['total_categories'] = count($category_counts);
  293. $data['earliest_report_time'] = $earliest_timestamp;
  294. $data['latest_report_time'] = $latest_timestamp;
  295. }
  296. return $data;
  297. }
  298. /**
  299. * Creates a new site in centralized stat tracker
  300. * @param sitename - name of the instance
  301. * @param url - base url
  302. */
  303. public function create_site( $sitename, $url )
  304. {
  305. $stat_url = 'http://tracker.ushahidi.com/px.php?task=cs&sitename='.urlencode($sitename).'&url='.urlencode($url);
  306. // Ignore errors since we are error checking later
  307. $xml = simplexml_load_string(Stats_Model::_curl_req($stat_url));
  308. $stat_id = (string) $xml->id[0];
  309. $stat_key = (string) $xml->key[0];
  310. if ($stat_id > 0){
  311. $settings = ORM::factory('settings',1);
  312. $settings->stat_id = $stat_id;
  313. $settings->stat_key = $stat_key;
  314. $settings->save();
  315. return $stat_id;
  316. }
  317. return false;
  318. }
  319. /**
  320. * Helper function to send a cURL request
  321. * @param url - URL for cURL to hit
  322. */
  323. public function _curl_req( $url )
  324. {
  325. // Make sure cURL is installed
  326. if ( ! function_exists('curl_exec')) {
  327. throw new Kohana_Exception('stats.cURL_not_installed');
  328. return false;
  329. }
  330. $curl_handle = curl_init();
  331. curl_setopt($curl_handle,CURLOPT_URL,$url);
  332. // Timeout set to 15 seconds. This is somewhat arbitrary and can be changed.
  333. curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,15);
  334. // Set curl to store data in variable instead of print
  335. curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
  336. $buffer = curl_exec($curl_handle);
  337. curl_close($curl_handle);
  338. return $buffer;
  339. }
  340. }