Events by day stats added. DAY() DQL function added.

This commit is contained in:
Alexey Skobkin 2017-01-10 04:21:57 +03:00
parent 8544d9c7c3
commit bfc40d595c
7 changed files with 149 additions and 8 deletions

View File

@ -57,6 +57,9 @@ doctrine:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
dql:
string_functions:
DAY: Skobkin\Bundle\PointToolsBundle\DQL\Day
doctrine_migrations:
dir_name: "%kernel.root_dir%/DoctrineMigrations"

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "f92c288e2df400d18133f9cfdfd97bbb",
"content-hash": "9b374e1b2cb413fbab3f0633d6f81c1a",
"packages": [
{
"name": "csa/guzzle-bundle",

View File

@ -3,6 +3,7 @@
namespace Skobkin\Bundle\PointToolsBundle\Controller;
use Doctrine\ORM\EntityManager;
use Skobkin\Bundle\PointToolsBundle\DTO\DailyEvents;
use Skobkin\Bundle\PointToolsBundle\DTO\TopUserDTO;
use Skobkin\Bundle\PointToolsBundle\Entity\User;
use Skobkin\Bundle\PointToolsBundle\Service\UserApi;
@ -49,22 +50,63 @@ class UserController extends Controller
public function topAction(): Response
{
$topUsers = $this->getDoctrine()->getManager()->getRepository('SkobkinPointToolsBundle:User')->getTopUsers();
$topChart = $this->createTopUsersGraph($topUsers);
$userRepo = $this->getDoctrine()->getManager()->getRepository('SkobkinPointToolsBundle:User');
$subscriptionsRecordsRepo = $this->getDoctrine()->getManager()->getRepository('SkobkinPointToolsBundle:SubscriptionEvent');
$topUsers = $userRepo->getTopUsers();
$eventsByDay = $subscriptionsRecordsRepo->getLastEventsByDay();
return $this->render('@SkobkinPointTools/User/top.html.twig', [
'top_users' => $topUsers,
'top_chart' => $topChart,
//'top_users' => $topUsers,
'events_dynamic_chat' => $this->createEventsDynamicChart($eventsByDay),
'top_chart' => $this->createTopUsersGraph($topUsers),
]);
}
/**
* @todo move to the service
*
* @param TopUserDTO[] $topUsers
* @param DailyEvents[] $eventsByDay
*/
private function createEventsDynamicChart(array $eventsByDay = []): Highchart
{
$translator = $this->get('translator');
$chartData = [
'titles' => [],
'events' => [],
];
foreach ($eventsByDay as $day) {
$chartData['titles'][] = $day->getDate()->format('d.m');
$chartData['events'][] = $day->getEventsCount();
}
$series = [[
'name' => $translator->trans('Events'),
'data' => $chartData['events'],
]];
$ob = new Highchart();
$ob->chart->renderTo('eventschart');
$ob->chart->type('line');
$ob->title->text($translator->trans('Events by day'));
$ob->xAxis->title(['text' => null]);
$ob->xAxis->categories($chartData['titles']);
$ob->yAxis->title(['text' => $translator->trans('amount')]);
$ob->plotOptions->bar([
'dataLabels' => [
'enabled' => true,
]
]);
$ob->series($series);
return $ob;
}
/**
* @todo move to the service
*
* @return Highchart
* @param TopUserDTO[] $topUsers
*/
private function createTopUsersGraph(array $topUsers = []): Highchart
{

View File

@ -0,0 +1,26 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
class Day extends FunctionNode
{
public $dateExpression;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->dateExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'date_trunc(\'day\', '.$this->dateExpression->dispatch($sqlWalker).')';
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace Skobkin\Bundle\PointToolsBundle\DTO;
/**
* Events count by day
*/
class DailyEvents
{
/**
* @var \DateTime
*/
private $date;
/**
* @var int
*/
private $eventsCount;
public function __construct(string $date, int $eventsCount)
{
$this->date = new \DateTime($date);
$this->eventsCount = $eventsCount;
}
public function getDate(): \DateTime
{
return $this->date;
}
public function getEventsCount(): int
{
return $this->eventsCount;
}
}

View File

@ -93,4 +93,34 @@ class SubscriptionEventRepository extends EntityRepository
return $qb->getQuery()->getResult();
}
/**
* @return SubscriptionEvent[]
*/
public function getLastEventsByDay(int $days = 30): array
{
$qb = $this->createQueryBuilder('se');
$rows = $qb
->select([
'NEW Skobkin\Bundle\PointToolsBundle\DTO\DailyEvents(DAY(se.date), COUNT(se))',
'DAY(se.date) as day',
])
->groupBy('day')
->orderBy('day', 'DESC')
->setMaxResults($days)
->getQuery()->getResult()
;
$result = [];
// Removing unnecessary element, saving DTO
// @todo remove crutches, refactor query
foreach ($rows as $row) {
unset($row['day']);
$result[] = reset($row);
}
return $result;
}
}

View File

@ -10,8 +10,13 @@
{% block content %}
<script type="text/javascript">
// Top chart
{{ chart(top_chart) }}
// Events by day chart
{{ chart(events_dynamic_chat) }}
</script>
<div id="topchart" style="min-width: 400px; height: 600px; margin: 0 auto;"></div>
<div id="eventschart" style="min-width: 400px; height: 600px; margin: 0 auto;"></div>
{% endblock %}