PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/application/models/stats.php

https://github.com/fayazv/Taarifa_Web
PHP | 456 lines | 290 code | 92 blank | 74 comment | 44 complexity | 3b8f43e4f2ae9c8f42af87bb7e047b63 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-3.0, BSD-3-Clause, LGPL-2.1
  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. * @subpackage Models
  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. static $time_out = 1;
  19. /*
  20. *
  21. *
  22. */
  23. static function get_javascript()
  24. {
  25. // Make sure cURL is installed
  26. if (!function_exists('curl_exec')) {
  27. throw new Kohana_Exception('footer.cURL_not_installed');
  28. return false;
  29. }
  30. $settings = ORM::factory('settings', 1);
  31. $stat_id = $settings->stat_id;
  32. // If stats isn't set, ignore this
  33. if($stat_id == 0) return '';
  34. $cache = Cache::instance();
  35. $tag = $cache->get(Kohana::config('settings.subdomain').'_piwiktag');
  36. if ( ! $tag)
  37. { // Cache is Empty so Re-Cache
  38. // Grabbing the URL to update stats URL, Name, Reports, etc on the stats server
  39. $additional_query = '';
  40. if (isset($_SERVER["HTTP_HOST"]))
  41. {
  42. // Grab the site domain from the config and trim any whitespaces
  43. $site_domain = trim(Kohana::config('config.site_domain'));
  44. $slashornoslash = '';
  45. if (empty($site_domain) OR $site_domain{0} != '/') $slashornoslash = '/';
  46. // URL
  47. $val = 'http://'.$_SERVER["HTTP_HOST"].$slashornoslash.$site_domain;
  48. $additional_query = '&val='.base64_encode($val);
  49. // Site Name
  50. $site_name = utf8tohtml::convert(Kohana::config('settings.site_name'),TRUE);
  51. $additional_query .= '&sitename='.base64_encode($site_name);
  52. // Version
  53. $version = Kohana::config('settings.ushahidi_version');
  54. $additional_query .= '&version='.base64_encode($version);
  55. // Report Count
  56. $number_reports = ORM::factory("incident")->where("incident_active", 1)->count_all();
  57. $additional_query .= '&reports='.base64_encode($number_reports);
  58. // Latitude
  59. $latitude = Kohana::config('settings.default_lat');
  60. $additional_query .= '&lat='.base64_encode($latitude);
  61. // Longitude
  62. $longitude = Kohana::config('settings.default_lon');
  63. $additional_query .= '&lon='.base64_encode($longitude);
  64. }
  65. $url = 'http://tracker.ushahidi.com/dev.px.php?task=tc&siteid='.$stat_id.$additional_query;
  66. $curl_handle = curl_init();
  67. curl_setopt($curl_handle,CURLOPT_URL,$url);
  68. curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,self::$time_out); // Timeout set to 15 seconds. This is somewhat arbitrary and can be changed.
  69. curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1); // Set cURL to store data in variable instead of print
  70. $buffer = curl_exec($curl_handle);
  71. curl_close($curl_handle);
  72. try {
  73. $tag = (string) @simplexml_load_string($buffer); // This works because the tracking code is only wrapped in one tag
  74. } catch (Exception $e) {
  75. // In case the xml was malformed for whatever reason, we will just guess what the tag should be here
  76. $tag = '<!-- Piwik --><script type="text/javascript">$(document).ready(function(){$(\'#piwik\').load(\'http://tracker.ushahidi.com/piwik/piwik.php?idsite='.$stat_id.'&rec=1\');});</script><div id="piwik"></div><!-- End Piwik Tag -->';
  77. }
  78. // Reset Cache Here
  79. $cache->set(Kohana::config('settings.subdomain').'_piwiktag', $tag, array('piwiktag'), 60); // 1 Day
  80. }
  81. return $tag;
  82. }
  83. /*
  84. * range will be ignored if dp1 and dp2 are set
  85. * dp1 and dp2 format is YYYY-MM-DD
  86. */
  87. static function get_hit_stats($range=30,$dp1=null,$dp2=null)
  88. {
  89. // Get ID for stats
  90. $settings = ORM::factory('settings', 1);
  91. $stat_id = $settings->stat_id;
  92. $twodates = '';
  93. if ($dp1 !== null AND $dp2 !== null) {
  94. $twodates = '&twodates='.urlencode($dp1.','.$dp2);
  95. }
  96. $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;
  97. // Ignore errors since we are error checking later
  98. $response = @simplexml_load_string(self::_curl_req($stat_url));
  99. // If we encounter an error, return false
  100. if (isset($response->result->error[0]) OR isset($response->error[0]) OR ! isset($response->visits->result)) {
  101. Kohana::log('error', "Error on stats request");
  102. return false;
  103. }
  104. foreach ($response->visits->result as $res) {
  105. $dt = $res['date'];
  106. $y = substr($dt,0,4);
  107. $m = substr($dt,5,2);
  108. $d = substr($dt,8,2);
  109. $timestamp = mktime(0,0,0,$m,$d,$y)*1000;
  110. if (isset($res->nb_visits)){
  111. $data['visits'][ (string) $timestamp] = (string) $res->nb_visits;
  112. }else{
  113. $data['visits'][ (string) $timestamp] = '0';
  114. }
  115. if (isset($res->nb_uniq_visitors)){
  116. $data['uniques'][ (string) $timestamp] = (string) $res->nb_uniq_visitors;
  117. }else{
  118. $data['uniques'][ (string) $timestamp] = '0';
  119. }
  120. if (isset($res->nb_actions)){
  121. $data['pageviews'][ (string) $timestamp] = (string) $res->nb_actions;
  122. }else{
  123. $data['pageviews'][ (string) $timestamp] = '0';
  124. }
  125. }
  126. return $data;
  127. }
  128. static function get_hit_countries($range=30,$dp1=null,$dp2=null)
  129. {
  130. $settings = ORM::factory('settings', 1);
  131. $stat_id = $settings->stat_id;
  132. $twodates = '';
  133. if ($dp1 !== null AND $dp2 !== null) {
  134. $twodates = '&twodates='.urlencode($dp1.','.$dp2);
  135. }
  136. $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;
  137. // Ignore errors since we are error checking later
  138. $response = @simplexml_load_string(self::_curl_req($stat_url));
  139. // If we encounter an error, return false
  140. if (isset($response->result->error[0]) OR isset($response->error[0]) OR ! isset($response->countries->result)) {
  141. Kohana::log('error', "Error on stats request");
  142. return false;
  143. }
  144. $data = array();
  145. foreach ($response->countries->result as $res) {
  146. $date = (string) $res['date'];
  147. foreach ($res->row as $row){
  148. $code = (string) $row->code;
  149. $data[$date][$code]['label'] = (string) $row->label;
  150. $data[$date][$code]['uniques'] = (string) $row->nb_uniq_visitors;
  151. $logo = (string) $row->logo;
  152. $data[$date][$code]['logo'] = 'http://tracker.ushahidi.com/piwik/'.$logo;
  153. }
  154. }
  155. return $data;
  156. }
  157. /*
  158. * get an array of report counts
  159. * @param approved - Only count approved reports if true
  160. * @param by_time - Format array with timestamp as the key if true
  161. * @param range - Number of days back from today to pull reports from. Will end up defaulting to 100000 days to get them all.
  162. * @param dp1 - Arbitrary date range. Low date. YYYY-MM-DD
  163. * @param dp2 - Arbitrary date range. High date. YYYY-MM-DD
  164. */
  165. static function get_report_stats($approved=false,$by_time=false,$range=null,$dp1=null,$dp2=null,$line_chart_data=false)
  166. {
  167. if ($range === null) {
  168. $range = 100000;
  169. }
  170. if ($dp1 === null) {
  171. $dp1 = 0;
  172. }
  173. if ($dp2 === null) {
  174. $dp2 = '3000-01-01';
  175. }
  176. // Set up the range calculation
  177. $time = time() - ($range*86400);
  178. $range_date = date('Y-m-d',$time);
  179. // Only grab approved
  180. if ($approved) {
  181. $reports = ORM::factory('incident')->where('incident_active','1')->where('incident_date >=',$dp1)->where('incident_date <=',$dp2)->where('incident_date >',$range_date)->find_all();
  182. }else{
  183. $reports = ORM::factory('incident')->where('incident_date >=',$dp1)->where('incident_date <=',$dp2)->where('incident_date >',$range_date)->find_all();
  184. }
  185. $reports_categories = ORM::factory('incident_category')->find_all();
  186. // Initialize arrays so we don't error out
  187. $report_data = array();
  188. $verified_counts = array();
  189. $approved_counts = array();
  190. $all = array();
  191. $earliest_timestamp = 32503680000; // Year 3000 in epoch so we can catch everything less than this.
  192. $latest_timestamp = 0;
  193. // Gather some data into an array on incident reports
  194. $num_reports = 0;
  195. foreach ($reports as $report) {
  196. $timestamp = (string) strtotime(substr($report->incident_date,0,10));
  197. $report_data[$report->id] = array(
  198. 'date'=>$timestamp,
  199. 'mode'=>$report->incident_mode,
  200. 'active'=>$report->incident_active,
  201. 'verified'=>$report->incident_verified
  202. );
  203. if ($timestamp < $earliest_timestamp) {
  204. $earliest_timestamp = $timestamp;
  205. }
  206. if ($timestamp > $latest_timestamp) {
  207. $latest_timestamp = $timestamp;
  208. }
  209. if ( ! isset($verified_counts['verified'][$timestamp])) {
  210. $verified_counts['verified'][$timestamp] = 0;
  211. $verified_counts['unverified'][$timestamp] = 0;
  212. $approved_counts['approved'][$timestamp] = 0;
  213. $approved_counts['unapproved'][$timestamp] = 0;
  214. $all[$timestamp] = 0;
  215. }
  216. $all[$timestamp]++;
  217. if ($report->incident_verified == 1){
  218. $verified_counts['verified'][$timestamp]++;
  219. }else{
  220. $verified_counts['unverified'][$timestamp]++;
  221. }
  222. if ($report->incident_active == 1){
  223. $approved_counts['approved'][$timestamp]++;
  224. }else{
  225. $approved_counts['unapproved'][$timestamp]++;
  226. }
  227. $num_reports++;
  228. }
  229. $category_counts = array();
  230. $lowest_date = 9999999999; // Really far in the future.
  231. $highest_date = 0;
  232. foreach ($reports_categories as $report){
  233. // if this report category doesn't have any reports (in case we are only
  234. // looking at approved reports), move on to the next one.
  235. if ( ! isset($report_data[$report->incident_id])) continue;
  236. $c_id = $report->category_id;
  237. $timestamp = $report_data[$report->incident_id]['date'];
  238. if ($timestamp < $lowest_date) {
  239. $lowest_date = $timestamp;
  240. }
  241. if ($timestamp > $highest_date) {
  242. $highest_date = $timestamp;
  243. }
  244. if ( ! isset($category_counts[$c_id][$timestamp])) {
  245. $category_counts[$c_id][$timestamp] = 0;
  246. }
  247. $category_counts[$c_id][$timestamp]++;
  248. }
  249. // Populate date range
  250. $date_range = array();
  251. $add_date = $lowest_date;
  252. while ($add_date <= $highest_date){
  253. $date_range[] = $add_date;
  254. $add_date += 86400;
  255. }
  256. // Zero out days that don't have a count
  257. foreach ($category_counts as & $arr) {
  258. foreach ($date_range as $timestamp){
  259. if ( ! isset($arr[$timestamp])) {
  260. $arr[$timestamp] = 0;
  261. }
  262. if ( ! isset($verified_counts['verified'][$timestamp])) {
  263. $verified_counts['verified'][$timestamp] = 0;
  264. }
  265. if ( ! isset($verified_counts['unverified'][$timestamp])) {
  266. $verified_counts['unverified'][$timestamp] = 0;
  267. }
  268. if ( ! isset($approved_counts['approved'][$timestamp])) {
  269. $approved_counts['approved'][$timestamp] = 0;
  270. }
  271. if ( ! isset($approved_counts['unapproved'][$timestamp])) {
  272. $approved_counts['unapproved'][$timestamp] = 0;
  273. }
  274. if ( ! isset($all[$timestamp])) {
  275. $all[$timestamp] = 0;
  276. }
  277. }
  278. // keep dates in order
  279. ksort($arr);
  280. ksort($verified_counts['verified']);
  281. ksort($verified_counts['unverified']);
  282. ksort($approved_counts['approved']);
  283. ksort($approved_counts['unapproved']);
  284. ksort($all);
  285. }
  286. // Add all our data sets to the array we are returning
  287. $data['category_counts'] = $category_counts;
  288. $data['verified_counts'] = $verified_counts;
  289. $data['approved_counts'] = $approved_counts;
  290. $data['all']['all'] = $all;
  291. // I'm just tacking this on here. However, we could improve performance
  292. // by implementing the code above but I just don't have the time
  293. // to mess with it.
  294. if ($by_time){
  295. // Reorder the array. Is there a built in PHP function that can do this?
  296. $new_data = array();
  297. foreach ($data as $main_key => $data_array){
  298. foreach ($data_array as $key => $counts){
  299. if ($line_chart_data == false){
  300. foreach ($counts as $timestamp => $count) $new_data[$main_key][$timestamp][$key] = $count;
  301. }else{
  302. foreach ($counts as $timestamp => $count){
  303. $timestamp_key = (string) ($timestamp*1000);
  304. if ( ! isset($new_data[$main_key][$timestamp_key])) {
  305. $new_data[$main_key][$timestamp_key] = 0;
  306. }
  307. $new_data[$main_key][$timestamp_key] += $count;
  308. }
  309. }
  310. }
  311. }
  312. $data = $new_data;
  313. }
  314. if ($line_chart_data == false) {
  315. $data['total_reports'] = $num_reports;
  316. $data['total_categories'] = count($category_counts);
  317. $data['earliest_report_time'] = $earliest_timestamp;
  318. $data['latest_report_time'] = $latest_timestamp;
  319. }
  320. return $data;
  321. }
  322. /**
  323. * Creates a new site in centralized stat tracker
  324. * @param sitename - name of the instance
  325. * @param url - base url
  326. */
  327. public function create_site( $sitename, $url )
  328. {
  329. $stat_url = 'http://tracker.ushahidi.com/px.php?task=cs&sitename='.urlencode($sitename).'&url='.urlencode($url);
  330. // Ignore errors since we are error checking later
  331. $xml = simplexml_load_string(Stats_Model::_curl_req($stat_url));
  332. $stat_id = (string) $xml->id[0];
  333. $stat_key = (string) $xml->key[0];
  334. if ($stat_id > 0){
  335. $settings = ORM::factory('settings',1);
  336. $settings->stat_id = $stat_id;
  337. $settings->stat_key = $stat_key;
  338. $settings->save();
  339. return $stat_id;
  340. }
  341. return false;
  342. }
  343. /**
  344. * Helper function to send a cURL request
  345. * @param url - URL for cURL to hit
  346. */
  347. public function _curl_req( $url )
  348. {
  349. // Make sure cURL is installed
  350. if ( ! function_exists('curl_exec')) {
  351. throw new Kohana_Exception('stats.cURL_not_installed');
  352. return false;
  353. }
  354. $curl_handle = curl_init();
  355. curl_setopt($curl_handle,CURLOPT_URL,$url);
  356. // Timeout set to 15 seconds. This is somewhat arbitrary and can be changed.
  357. curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT, 15);
  358. // Set curl to store data in variable instead of print
  359. curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
  360. $buffer = curl_exec($curl_handle);
  361. curl_close($curl_handle);
  362. return $buffer;
  363. }
  364. }