/intromagang/blog/user/plugins/admin/classes/popularity.php

https://gitlab.com/akbaryu/intro_magang_web · PHP · 296 lines · 199 code · 54 blank · 43 comment · 30 complexity · 3e039fb4c83e5b69967c0e9ca613818f MD5 · raw file

  1. <?php
  2. namespace Grav\Plugin;
  3. use Grav\Common\Config\Config;
  4. use Grav\Common\Grav;
  5. use Grav\Common\Page\Page;
  6. use Grav\Common\Data;
  7. /**
  8. * Class Popularity
  9. * @package Grav\Plugin
  10. */
  11. class Popularity
  12. {
  13. /** @var Config */
  14. protected $config;
  15. protected $data_path;
  16. protected $daily_file;
  17. protected $monthly_file;
  18. protected $totals_file;
  19. protected $visitors_file;
  20. protected $daily_data;
  21. protected $monthly_data;
  22. protected $totals_data;
  23. protected $visitors_data;
  24. const DAILY_FORMAT = 'd-m-Y';
  25. const MONTHLY_FORMAT = 'm-Y';
  26. const DAILY_FILE = 'daily.json';
  27. const MONTHLY_FILE = 'monthly.json';
  28. const TOTALS_FILE = 'totals.json';
  29. const VISITORS_FILE = 'visitors.json';
  30. public function __construct()
  31. {
  32. $this->config = Grav::instance()['config'];
  33. $this->data_path = Grav::instance()['locator']->findResource('log://popularity', true, true);
  34. $this->daily_file = $this->data_path . '/' . self::DAILY_FILE;
  35. $this->monthly_file = $this->data_path . '/' . self::MONTHLY_FILE;
  36. $this->totals_file = $this->data_path . '/' . self::TOTALS_FILE;
  37. $this->visitors_file = $this->data_path . '/' . self::VISITORS_FILE;
  38. }
  39. public function trackHit()
  40. {
  41. // Don't track bot or crawler requests
  42. if (!Grav::instance()['browser']->isHuman()) {
  43. return;
  44. }
  45. /** @var Page $page */
  46. $page = Grav::instance()['page'];
  47. $relative_url = str_replace(Grav::instance()['base_url_relative'], '', $page->url());
  48. // Don't track error pages or pages that have no route
  49. if ($page->template() == 'error' || !$page->route()) {
  50. return;
  51. }
  52. // Make sure no 'widcard-style' ignore matches this url
  53. foreach ((array)$this->config->get('plugins.admin.popularity.ignore') as $ignore) {
  54. if (fnmatch($ignore, $relative_url)) {
  55. return;
  56. }
  57. }
  58. // initial creation if it doesn't exist
  59. if (!file_exists($this->data_path)) {
  60. mkdir($this->data_path);
  61. $this->flushPopularity();
  62. }
  63. // Update the data we want to track
  64. $this->updateDaily();
  65. $this->updateMonthly();
  66. $this->updateTotals($page->route());
  67. $this->updateVisitors(Grav::instance()['uri']->ip());
  68. }
  69. protected function updateDaily()
  70. {
  71. if (!$this->daily_data) {
  72. $this->daily_data = $this->getData($this->daily_file);
  73. }
  74. $day_month_year = date(self::DAILY_FORMAT);
  75. // get the daily access count
  76. if (array_key_exists($day_month_year, $this->daily_data)) {
  77. $this->daily_data[$day_month_year] = intval($this->daily_data[$day_month_year]) + 1;
  78. } else {
  79. $this->daily_data[$day_month_year] = 1;
  80. }
  81. // keep correct number as set by history
  82. $count = intval($this->config->get('plugins.admin.popularity.history.daily', 30));
  83. $total = count($this->daily_data);
  84. if ($total > $count) {
  85. $this->daily_data = array_slice($this->daily_data, -$count, $count, true);
  86. }
  87. file_put_contents($this->daily_file, json_encode($this->daily_data));
  88. }
  89. /**
  90. * @return array
  91. */
  92. public function getDailyChartData()
  93. {
  94. if (!$this->daily_data) {
  95. $this->daily_data = $this->getData($this->daily_file);
  96. }
  97. $limit = intval($this->config->get('plugins.admin.popularity.dashboard.days_of_stats', 7));
  98. $chart_data = array_slice($this->daily_data, -$limit, $limit);
  99. $labels = [];
  100. $data = [];
  101. foreach ($chart_data as $date => $count) {
  102. $labels[] = Grav::instance()['grav']['admin']->translate([
  103. 'PLUGIN_ADMIN.' . strtoupper(date('D', strtotime($date)))
  104. ]);
  105. $data[] = $count;
  106. }
  107. return ['labels' => $labels, 'data' => $data];
  108. }
  109. /**
  110. * @return int
  111. */
  112. public function getDailyTotal()
  113. {
  114. if (!$this->daily_data) {
  115. $this->daily_data = $this->getData($this->daily_file);
  116. }
  117. if (isset($this->daily_data[date(self::DAILY_FORMAT)])) {
  118. return $this->daily_data[date(self::DAILY_FORMAT)];
  119. } else {
  120. return 0;
  121. }
  122. }
  123. /**
  124. * @return int
  125. */
  126. public function getWeeklyTotal()
  127. {
  128. if (!$this->daily_data) {
  129. $this->daily_data = $this->getData($this->daily_file);
  130. }
  131. $day = 0;
  132. $total = 0;
  133. foreach (array_reverse($this->daily_data) as $daily) {
  134. $total += $daily;
  135. $day++;
  136. if ($day == 7) {
  137. break;
  138. }
  139. }
  140. return $total;
  141. }
  142. /**
  143. * @return int
  144. */
  145. public function getMonthlyTotal()
  146. {
  147. if (!$this->monthly_data) {
  148. $this->monthly_data = $this->getData($this->monthly_file);
  149. }
  150. if (isset($this->monthly_data[date(self::MONTHLY_FORMAT)])) {
  151. return $this->monthly_data[date(self::MONTHLY_FORMAT)];
  152. } else {
  153. return 0;
  154. }
  155. }
  156. protected function updateMonthly()
  157. {
  158. if (!$this->monthly_data) {
  159. $this->monthly_data = $this->getData($this->monthly_file);
  160. }
  161. $month_year = date(self::MONTHLY_FORMAT);
  162. // get the monthly access count
  163. if (array_key_exists($month_year, $this->monthly_data)) {
  164. $this->monthly_data[$month_year] = intval($this->monthly_data[$month_year]) + 1;
  165. } else {
  166. $this->monthly_data[$month_year] = 1;
  167. }
  168. // keep correct number as set by history
  169. $count = intval($this->config->get('plugins.admin.popularity.history.monthly', 12));
  170. $total = count($this->monthly_data);
  171. $this->monthly_data = array_slice($this->monthly_data, $total - $count, $count);
  172. file_put_contents($this->monthly_file, json_encode($this->monthly_data));
  173. }
  174. /**
  175. * @return array
  176. */
  177. protected function getMonthyChartData()
  178. {
  179. if (!$this->monthly_data) {
  180. $this->monthly_data = $this->getData($this->monthly_file);
  181. }
  182. $labels = [];
  183. $data = [];
  184. foreach ($this->monthly_data as $date => $count) {
  185. $labels[] = date('M', strtotime($date));
  186. $data[] = $count;
  187. }
  188. return ['labels' => $labels, 'data' => $data];
  189. }
  190. /**
  191. * @param string $url
  192. */
  193. protected function updateTotals($url)
  194. {
  195. if (!$this->totals_data) {
  196. $this->totals_data = $this->getData($this->totals_file);
  197. }
  198. // get the totals for this url
  199. if (array_key_exists($url, $this->totals_data)) {
  200. $this->totals_data[$url] = intval($this->totals_data[$url]) + 1;
  201. } else {
  202. $this->totals_data[$url] = 1;
  203. }
  204. file_put_contents($this->totals_file, json_encode($this->totals_data));
  205. }
  206. /**
  207. * @param string $ip
  208. */
  209. protected function updateVisitors($ip)
  210. {
  211. if (!$this->visitors_data) {
  212. $this->visitors_data = $this->getData($this->visitors_file);
  213. }
  214. // update with current timestamp
  215. $this->visitors_data[$ip] = time();
  216. $visitors = $this->visitors_data;
  217. arsort($visitors);
  218. $count = intval($this->config->get('plugins.admin.popularity.history.visitors', 20));
  219. $this->visitors_data = array_slice($visitors, 0, $count, true);
  220. file_put_contents($this->visitors_file, json_encode($this->visitors_data));
  221. }
  222. /**
  223. * @param string $path
  224. *
  225. * @return array
  226. */
  227. protected function getData($path)
  228. {
  229. if (file_exists($path)) {
  230. return (array)json_decode(file_get_contents($path), true);
  231. } else {
  232. return [];
  233. }
  234. }
  235. public function flushPopularity()
  236. {
  237. file_put_contents($this->daily_file, []);
  238. file_put_contents($this->monthly_file, []);
  239. file_put_contents($this->totals_file, []);
  240. file_put_contents($this->visitors_file, []);
  241. }
  242. }