commit
cfe273796d
9 changed files with 378 additions and 3 deletions
@ -0,0 +1,178 @@ |
||||
<?php |
||||
|
||||
class FreshRSS_StatsDAO extends Minz_ModelPdo { |
||||
|
||||
/** |
||||
* Calculates entry repartition for all feeds and for main stream. |
||||
* The repartition includes: |
||||
* - total entries |
||||
* - read entries |
||||
* - unread entries |
||||
* - favorite entries |
||||
* |
||||
* @return type |
||||
*/ |
||||
public function calculateEntryRepartition() { |
||||
$repartition = array(); |
||||
|
||||
// Generates the repartition for the main stream of entry |
||||
$sql = <<<SQL |
||||
SELECT COUNT(1) AS `total`, |
||||
COUNT(1) - SUM(e.is_read) AS `unread`, |
||||
SUM(e.is_read) AS `read`, |
||||
SUM(e.is_favorite) AS `favorite` |
||||
FROM {$this->prefix}entry AS e |
||||
, {$this->prefix}feed AS f |
||||
WHERE e.id_feed = f.id |
||||
AND f.priority = 10 |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
$repartition['main_stream'] = $res[0]; |
||||
|
||||
// Generates the repartition for all entries |
||||
$sql = <<<SQL |
||||
SELECT COUNT(1) AS `total`, |
||||
COUNT(1) - SUM(e.is_read) AS `unread`, |
||||
SUM(e.is_read) AS `read`, |
||||
SUM(e.is_favorite) AS `favorite` |
||||
FROM {$this->prefix}entry AS e |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
$repartition['all_feeds'] = $res[0]; |
||||
|
||||
return $repartition; |
||||
} |
||||
|
||||
/** |
||||
* Calculates entry count per day on a 30 days period. |
||||
* Returns the result as a JSON string. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function calculateEntryCount() { |
||||
$count = array(); |
||||
|
||||
// Generates a list of 30 last day to be sure we always have 30 days. |
||||
// If we do not do that kind of thing, we'll end up with holes in the |
||||
// days if the user do not have a lot of feeds. |
||||
$sql = <<<SQL |
||||
SELECT - (tens.val + units.val + 1) AS day |
||||
FROM ( |
||||
SELECT 0 AS val |
||||
UNION ALL SELECT 1 |
||||
UNION ALL SELECT 2 |
||||
UNION ALL SELECT 3 |
||||
UNION ALL SELECT 4 |
||||
UNION ALL SELECT 5 |
||||
UNION ALL SELECT 6 |
||||
UNION ALL SELECT 7 |
||||
UNION ALL SELECT 8 |
||||
UNION ALL SELECT 9 |
||||
) AS units |
||||
CROSS JOIN ( |
||||
SELECT 0 AS val |
||||
UNION ALL SELECT 10 |
||||
UNION ALL SELECT 20 |
||||
) AS tens |
||||
ORDER BY day ASC |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
foreach ($res as $value) { |
||||
$count[$value['day']] = 0; |
||||
} |
||||
|
||||
// Get stats per day for the last 30 days and applies the result on |
||||
// the array created with the last query. |
||||
$sql = <<<SQL |
||||
SELECT DATEDIFF(FROM_UNIXTIME(e.date), NOW()) AS day, |
||||
COUNT(1) AS count |
||||
FROM {$this->prefix}entry AS e |
||||
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') |
||||
GROUP BY day |
||||
ORDER BY day ASC |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
|
||||
foreach ($res as $value) { |
||||
$count[$value['day']] = (int) $value['count']; |
||||
} |
||||
|
||||
return $this->convertToSerie($count); |
||||
} |
||||
|
||||
/** |
||||
* Calculates feed count per category. |
||||
* Returns the result as a JSON string. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function calculateFeedByCategory() { |
||||
$sql = <<<SQL |
||||
SELECT c.name AS label |
||||
, COUNT(f.id) AS data |
||||
FROM {$this->prefix}category AS c, |
||||
{$this->prefix}feed AS f |
||||
WHERE c.id = f.category |
||||
GROUP BY label |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
|
||||
return $this->convertToPieSerie($res); |
||||
} |
||||
|
||||
/** |
||||
* Calculates entry count per category. |
||||
* Returns the result as a JSON string. |
||||
* |
||||
* @return string |
||||
*/ |
||||
public function calculateEntryByCategory() { |
||||
$sql = <<<SQL |
||||
SELECT c.name AS label |
||||
, COUNT(e.id) AS data |
||||
FROM {$this->prefix}category AS c, |
||||
{$this->prefix}feed AS f, |
||||
{$this->prefix}entry AS e |
||||
WHERE c.id = f.category |
||||
AND f.id = e.id_feed |
||||
GROUP BY label |
||||
SQL; |
||||
$stm = $this->bd->prepare($sql); |
||||
$stm->execute(); |
||||
$res = $stm->fetchAll(PDO::FETCH_ASSOC); |
||||
|
||||
return $this->convertToPieSerie($res); |
||||
} |
||||
|
||||
private function convertToSerie($data) { |
||||
$serie = array(); |
||||
|
||||
foreach ($data as $key => $value) { |
||||
$serie[] = array($key, $value); |
||||
} |
||||
|
||||
return json_encode($serie); |
||||
} |
||||
|
||||
private function convertToPieSerie($data) { |
||||
$serie = array(); |
||||
|
||||
foreach ($data as $value) { |
||||
$value['data'] = array(array(0, (int)$value['data'])); |
||||
$serie[] = $value; |
||||
} |
||||
|
||||
return json_encode($serie); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,92 @@ |
||||
<div class="post content"> |
||||
<a href="<?php echo _url ('index', 'index'); ?>"><?php echo Minz_Translate::t ('back_to_rss_feeds'); ?></a>
|
||||
|
||||
<h1><?php echo Minz_Translate::t ('stats'); ?></h1>
|
||||
|
||||
<div class="stat"> |
||||
<h2><?php echo Minz_Translate::t ('stats_entry_repartition')?></h2>
|
||||
<table> |
||||
<thead> |
||||
<tr> |
||||
<th> </th> |
||||
<th><?php echo Minz_Translate::t ('main_stream')?></th>
|
||||
<th><?php echo Minz_Translate::t ('all_feeds')?></th>
|
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<th><?php echo Minz_Translate::t ('status_total')?></th>
|
||||
<td><?php echo $this->repartition['main_stream']['total']?></td>
|
||||
<td><?php echo $this->repartition['all_feeds']['total']?></td>
|
||||
</tr> |
||||
<tr> |
||||
<th><?php echo Minz_Translate::t ('status_read')?></th>
|
||||
<td><?php echo $this->repartition['main_stream']['read']?></td>
|
||||
<td><?php echo $this->repartition['all_feeds']['read']?></td>
|
||||
</tr> |
||||
<tr> |
||||
<th><?php echo Minz_Translate::t ('status_unread')?></th>
|
||||
<td><?php echo $this->repartition['main_stream']['unread']?></td>
|
||||
<td><?php echo $this->repartition['all_feeds']['unread']?></td>
|
||||
</tr> |
||||
<tr> |
||||
<th><?php echo Minz_Translate::t ('status_favorites')?></th>
|
||||
<td><?php echo $this->repartition['main_stream']['favorite']?></td>
|
||||
<td><?php echo $this->repartition['all_feeds']['favorite']?></td>
|
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
|
||||
<div class="stat"> |
||||
<h2><?php echo Minz_Translate::t ('stats_entry_per_day')?></h2>
|
||||
<div id="statsEntryPerDay" style="height: 300px"></div> |
||||
</div> |
||||
|
||||
<div class="stat"> |
||||
<h2><?php echo Minz_Translate::t ('stats_feed_per_category')?></h2>
|
||||
<div id="statsFeedPerCategory" style="height: 300px"></div> |
||||
<div id="statsFeedPerCategoryLegend"></div> |
||||
</div> |
||||
|
||||
<div class="stat"> |
||||
<h2><?php echo Minz_Translate::t ('stats_entry_per_category')?></h2>
|
||||
<div id="statsEntryPerCategory" style="height: 300px"></div> |
||||
<div id="statsEntryPerCategoryLegend"></div> |
||||
</div> |
||||
|
||||
</div> |
||||
|
||||
<script> |
||||
// Entry per day |
||||
Flotr.draw(document.getElementById('statsEntryPerDay'), |
||||
[<?php echo $this->count ?>],
|
||||
{ |
||||
bars: {horizontal: false, show: true}, |
||||
xaxis: {noTicks: 6, showLabels: false, tickDecimals: 0}, |
||||
yaxis: {showLabels: false}, |
||||
mouse: {relative: true, track: true, trackDecimals: 0,trackFormatter: function(obj) {return obj.y;}} |
||||
}); |
||||
// Feed per category |
||||
Flotr.draw(document.getElementById('statsFeedPerCategory'), |
||||
<?php echo $this->feedByCategory ?>,
|
||||
{ |
||||
grid: {verticalLines: false, horizontalLines: false}, |
||||
pie: {explode: 2, show: true}, |
||||
xaxis: {showLabels: false}, |
||||
yaxis: {showLabels: false}, |
||||
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return obj.y;}}, |
||||
legend: {container: document.getElementById('statsFeedPerCategoryLegend')} |
||||
}); |
||||
// Entry per category |
||||
Flotr.draw(document.getElementById('statsEntryPerCategory'), |
||||
<?php echo $this->entryByCategory ?>,
|
||||
{ |
||||
grid: {verticalLines: false, horizontalLines: false}, |
||||
pie: {explode: 2, show: true}, |
||||
xaxis: {showLabels: false}, |
||||
yaxis: {showLabels: false}, |
||||
mouse: {relative: true, track: true, trackDecimals: 0, trackFormatter: function(obj) {return obj.y;}}, |
||||
legend: {container: document.getElementById('statsEntryPerCategoryLegend')} |
||||
}); |
||||
</script> |
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue