StatsDAO.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. class FreshRSS_StatsDAO extends Minz_ModelPdo {
  3. /**
  4. * Calculates entry repartition for all feeds and for main stream.
  5. * The repartition includes:
  6. * - total entries
  7. * - read entries
  8. * - unread entries
  9. * - favorite entries
  10. *
  11. * @return type
  12. */
  13. public function calculateEntryRepartition() {
  14. $repartition = array();
  15. // Generates the repartition for the main stream of entry
  16. $sql = <<<SQL
  17. SELECT COUNT(1) AS `total`,
  18. COUNT(1) - SUM(e.is_read) AS `unread`,
  19. SUM(e.is_read) AS `read`,
  20. SUM(e.is_favorite) AS `favorite`
  21. FROM {$this->prefix}entry AS e
  22. , {$this->prefix}feed AS f
  23. WHERE e.id_feed = f.id
  24. AND f.priority = 10
  25. SQL;
  26. $stm = $this->bd->prepare($sql);
  27. $stm->execute();
  28. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  29. $repartition['main_stream'] = $res[0];
  30. // Generates the repartition for all entries
  31. $sql = <<<SQL
  32. SELECT COUNT(1) AS `total`,
  33. COUNT(1) - SUM(e.is_read) AS `unread`,
  34. SUM(e.is_read) AS `read`,
  35. SUM(e.is_favorite) AS `favorite`
  36. FROM {$this->prefix}entry AS e
  37. SQL;
  38. $stm = $this->bd->prepare($sql);
  39. $stm->execute();
  40. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  41. $repartition['all_feeds'] = $res[0];
  42. return $repartition;
  43. }
  44. /**
  45. * Calculates entry count per day on a 30 days period.
  46. * Returns the result as a JSON string.
  47. *
  48. * @return string
  49. */
  50. public function calculateEntryCount() {
  51. $count = array();
  52. // Generates a list of 30 last day to be sure we always have 30 days.
  53. // If we do not do that kind of thing, we'll end up with holes in the
  54. // days if the user do not have a lot of feeds.
  55. $sql = <<<SQL
  56. SELECT - (tens.val + units.val + 1) AS day
  57. FROM (
  58. SELECT 0 AS val
  59. UNION ALL SELECT 1
  60. UNION ALL SELECT 2
  61. UNION ALL SELECT 3
  62. UNION ALL SELECT 4
  63. UNION ALL SELECT 5
  64. UNION ALL SELECT 6
  65. UNION ALL SELECT 7
  66. UNION ALL SELECT 8
  67. UNION ALL SELECT 9
  68. ) AS units
  69. CROSS JOIN (
  70. SELECT 0 AS val
  71. UNION ALL SELECT 10
  72. UNION ALL SELECT 20
  73. ) AS tens
  74. ORDER BY day ASC
  75. SQL;
  76. $stm = $this->bd->prepare($sql);
  77. $stm->execute();
  78. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  79. foreach ($res as $value) {
  80. $count[$value['day']] = 0;
  81. }
  82. // Get stats per day for the last 30 days and applies the result on
  83. // the array created with the last query.
  84. $sql = <<<SQL
  85. SELECT DATEDIFF(FROM_UNIXTIME(e.date), NOW()) AS day,
  86. COUNT(1) AS count
  87. FROM {$this->prefix}entry AS e
  88. WHERE FROM_UNIXTIME(e.date, '%Y%m%d') BETWEEN DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -30 DAY), '%Y%m%d') AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 DAY), '%Y%m%d')
  89. GROUP BY day
  90. ORDER BY day ASC
  91. SQL;
  92. $stm = $this->bd->prepare($sql);
  93. $stm->execute();
  94. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  95. foreach ($res as $value) {
  96. $count[$value['day']] = (int) $value['count'];
  97. }
  98. return $this->convertToSerie($count);
  99. }
  100. /**
  101. * Calculates feed count per category.
  102. * Returns the result as a JSON string.
  103. *
  104. * @return string
  105. */
  106. public function calculateFeedByCategory() {
  107. $sql = <<<SQL
  108. SELECT c.name AS label
  109. , COUNT(f.id) AS data
  110. FROM {$this->prefix}category AS c,
  111. {$this->prefix}feed AS f
  112. WHERE c.id = f.category
  113. GROUP BY label
  114. ORDER BY data DESC
  115. SQL;
  116. $stm = $this->bd->prepare($sql);
  117. $stm->execute();
  118. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  119. return $this->convertToPieSerie($res);
  120. }
  121. /**
  122. * Calculates entry count per category.
  123. * Returns the result as a JSON string.
  124. *
  125. * @return string
  126. */
  127. public function calculateEntryByCategory() {
  128. $sql = <<<SQL
  129. SELECT c.name AS label
  130. , COUNT(e.id) AS data
  131. FROM {$this->prefix}category AS c,
  132. {$this->prefix}feed AS f,
  133. {$this->prefix}entry AS e
  134. WHERE c.id = f.category
  135. AND f.id = e.id_feed
  136. GROUP BY label
  137. ORDER BY data DESC
  138. SQL;
  139. $stm = $this->bd->prepare($sql);
  140. $stm->execute();
  141. $res = $stm->fetchAll(PDO::FETCH_ASSOC);
  142. return $this->convertToPieSerie($res);
  143. }
  144. /**
  145. * Calculates the 10 top feeds based on their number of entries
  146. *
  147. * @return array
  148. */
  149. public function calculateTopFeed() {
  150. $sql = <<<SQL
  151. SELECT f.id AS id
  152. , MAX(f.name) AS name
  153. , MAX(c.name) AS category
  154. , COUNT(e.id) AS count
  155. FROM {$this->prefix}category AS c,
  156. {$this->prefix}feed AS f,
  157. {$this->prefix}entry AS e
  158. WHERE c.id = f.category
  159. AND f.id = e.id_feed
  160. GROUP BY id
  161. ORDER BY count DESC
  162. LIMIT 10
  163. SQL;
  164. $stm = $this->bd->prepare($sql);
  165. $stm->execute();
  166. return $stm->fetchAll(PDO::FETCH_ASSOC);
  167. }
  168. private function convertToSerie($data) {
  169. $serie = array();
  170. foreach ($data as $key => $value) {
  171. $serie[] = array($key, $value);
  172. }
  173. return json_encode($serie);
  174. }
  175. private function convertToPieSerie($data) {
  176. $serie = array();
  177. foreach ($data as $value) {
  178. $value['data'] = array(array(0, (int) $value['data']));
  179. $serie[] = $value;
  180. }
  181. return json_encode($serie);
  182. }
  183. }