add mobile and desktop views

This commit is contained in:
Simon Vieille 2022-02-25 15:15:09 +01:00
parent 4db7936a2c
commit 33eec52044
9 changed files with 125 additions and 24 deletions

1
.php-version Normal file
View file

@ -0,0 +1 @@
8.0

View file

@ -1,5 +1,13 @@
## [Unreleased] ## [Unreleased]
### Commands
```
composer remove jaybizzle/crawler-detect
composer require matomo/device-detector
make doctrine-migration
```
## Upgrade to v1.4.0 ## Upgrade to v1.4.0
### Commands ### Commands

View file

@ -21,6 +21,7 @@
"knplabs/doctrine-behaviors": "^2.6", "knplabs/doctrine-behaviors": "^2.6",
"knplabs/knp-paginator-bundle": "^5.8", "knplabs/knp-paginator-bundle": "^5.8",
"liip/imagine-bundle": "^2.7", "liip/imagine-bundle": "^2.7",
"matomo/device-detector": "^5.0",
"phpdocumentor/reflection-docblock": "^5.3", "phpdocumentor/reflection-docblock": "^5.3",
"scheb/2fa-google-authenticator": "^5.13", "scheb/2fa-google-authenticator": "^5.13",
"scheb/2fa-qr-code": "^5.13", "scheb/2fa-qr-code": "^5.13",

View file

@ -57,8 +57,6 @@ class DateRangeAnalytic
$datas[$index] += $entity->getViews(); $datas[$index] += $entity->getViews();
} }
arsort($datas, SORT_NUMERIC);
return $datas; return $datas;
} }
@ -73,13 +71,29 @@ class DateRangeAnalytic
$index = $entity->getPath(); $index = $entity->getPath();
if (!isset($datas[$index])) { if (!isset($datas[$index])) {
$datas[$index] = 0; $datas[$index] = [
'views' => 0,
'desktopViews' => 0,
'mobileViews' => 0,
];
} }
$datas[$index] += $entity->getViews(); $datas[$index]['views'] += $entity->getViews();
$datas[$index]['desktopViews'] += $entity->getDesktopViews();
$datas[$index]['mobileViews'] += $entity->getMobileViews();
} }
arsort($datas, SORT_NUMERIC); uasort($datas, function($a, $b) {
if ($a['views'] > $b['views']) {
return -1;
}
if ($a['views'] < $b['views']) {
return 1;
}
return 0;
});
return $datas; return $datas;
} }

View file

@ -21,7 +21,7 @@ class Referer implements EntityInterface
protected $id; protected $id;
/** /**
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="nodeViews") * @ORM\ManyToOne(targetEntity=Node::class, inversedBy="analyticReferers")
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE") * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*/ */
protected $node; protected $node;

View file

@ -21,7 +21,7 @@ class View implements EntityInterface
protected $id; protected $id;
/** /**
* @ORM\ManyToOne(targetEntity=Node::class, inversedBy="nodeViews") * @ORM\ManyToOne(targetEntity=Node::class, inversedBy="analyticViews")
* @ORM\JoinColumn(nullable=false, onDelete="CASCADE") * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
*/ */
protected $node; protected $node;
@ -36,6 +36,16 @@ class View implements EntityInterface
*/ */
protected $views = 0; protected $views = 0;
/**
* @ORM\Column(type="integer", options={"default"=0})
*/
protected $desktopViews = 0;
/**
* @ORM\Column(type="integer", options={"default"=0})
*/
protected $mobileViews = 0;
/** /**
* @ORM\Column(type="date") * @ORM\Column(type="date")
*/ */
@ -89,6 +99,44 @@ class View implements EntityInterface
return $this; return $this;
} }
public function getDesktopViews(): ?int
{
return $this->desktopViews;
}
public function setDesktopViews(int $desktopViews): self
{
$this->desktopViews = $desktopViews;
return $this;
}
public function addDesktopView(): self
{
++$this->desktopViews;
return $this;
}
public function getMobileViews(): ?int
{
return $this->mobileViews;
}
public function setMobileViews(int $mobileViews): self
{
$this->mobileViews = $mobileViews;
return $this;
}
public function addMobileView(): self
{
++$this->mobileViews;
return $this;
}
public function getDate(): ?\DateTimeInterface public function getDate(): ?\DateTimeInterface
{ {
return $this->date; return $this->date;

View file

@ -2,18 +2,19 @@
namespace App\Core\EventListener; namespace App\Core\EventListener;
use App\Core\Manager\EntityManager;
use App\Core\Repository\Site\NodeRepositoryQuery;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use App\Core\Repository\Site\NodeRepository;
use App\Core\Repository\Analytic\ViewRepositoryQuery;
use App\Core\Factory\Analytic\ViewFactory;
use App\Core\Entity\Site\Node;
use Symfony\Component\HttpFoundation\Request;
use App\Core\Repository\Analytic\RefererRepositoryQuery;
use App\Core\Factory\Analytic\RefererFactory;
use App\Core\Entity\EntityInterface; use App\Core\Entity\EntityInterface;
use Jaybizzle\CrawlerDetect\CrawlerDetect; use App\Core\Entity\Site\Node;
use App\Core\Factory\Analytic\RefererFactory;
use App\Core\Factory\Analytic\ViewFactory;
use App\Core\Manager\EntityManager;
use App\Core\Repository\Analytic\RefererRepositoryQuery;
use App\Core\Repository\Analytic\ViewRepositoryQuery;
use App\Core\Repository\Site\NodeRepository;
use DeviceDetector\Cache\PSR6Bridge;
use DeviceDetector\DeviceDetector;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
/** /**
* class AnalyticListener. * class AnalyticListener.
@ -28,7 +29,7 @@ class AnalyticListener
protected RefererRepositoryQuery $refererRepositoryQuery; protected RefererRepositoryQuery $refererRepositoryQuery;
protected RefererFactory $refererFactory; protected RefererFactory $refererFactory;
protected EntityManager $manager; protected EntityManager $manager;
protected CrawlerDetect $crawlerDetect; protected DeviceDetector $deviceDetector;
protected Request $request; protected Request $request;
protected Node $node; protected Node $node;
@ -46,7 +47,7 @@ class AnalyticListener
$this->refererRepositoryQuery = $refererRepositoryQuery; $this->refererRepositoryQuery = $refererRepositoryQuery;
$this->refererFactory = $refererFactory; $this->refererFactory = $refererFactory;
$this->manager = $manager; $this->manager = $manager;
$this->crawlerDetect = new CrawlerDetect(); $this->createDeviceDetector();
} }
public function onKernelRequest(RequestEvent $event) public function onKernelRequest(RequestEvent $event)
@ -57,7 +58,10 @@ class AnalyticListener
return; return;
} }
if ($this->crawlerDetect->isCrawler($request->headers->get('user-agent'))) { $this->deviceDetector->setUserAgent($request->headers->get('user-agent'));
$this->deviceDetector->parse();
if ($this->deviceDetector->isBot()) {
return; return;
} }
@ -77,6 +81,14 @@ class AnalyticListener
$this->createReferer(); $this->createReferer();
} }
protected function createDeviceDetector()
{
$cache = new ApcuAdapter();
$this->deviceDetector = new DeviceDetector();
$this->deviceDetector->setCache(new PSR6Bridge($cache));
}
protected function createView() protected function createView()
{ {
$entity = $this->viewRepositoryQuery->create() $entity = $this->viewRepositoryQuery->create()
@ -90,6 +102,13 @@ class AnalyticListener
} }
$entity->addView(); $entity->addView();
if ($this->deviceDetector->isDesktop()) {
$entity->addDesktopView();
} elseif ($this->deviceDetector->isMobile()) {
$entity->addMobileView();
}
$this->save($entity); $this->save($entity);
} }

View file

@ -47,18 +47,22 @@
<thead> <thead>
<tr> <tr>
<th>{{ 'Path'|trans }}</th> <th>{{ 'Path'|trans }}</th>
<th width="100" class="text-right">{{ 'Views'|trans }}</th> <th width="50" class="text-right">{{ 'Views'|trans }}</th>
<th width="50" class="text-right"><span class="fa fa-desktop"></span></th>
<th width="50" class="text-right"><span class="fa fa-mobile-alt"></span></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for path, views in pathViews %} {% for path, views in pathViews %}
<tr> <tr>
<td>{{ path }}</td> <td>{{ path }}</td>
<td class="text-right">{{ views }}</td> <td class="text-right">{{ views.views }}</td>
<td class="text-right">{{ views.desktopViews }}</td>
<td class="text-right">{{ views.mobileViews }}</td>
</tr> </tr>
{% else %} {% else %}
<tr> <tr>
<td class="col-12 text-center p-4 text-black-50" colspan="2"> <td class="col-12 text-center p-4 text-black-50" colspan="4">
<div class="display-1"> <div class="display-1">
<span class="fa fa-search"></span> <span class="fa fa-search"></span>
</div> </div>

View file

@ -160,9 +160,15 @@
"config/routes/liip_imagine.yaml" "config/routes/liip_imagine.yaml"
] ]
}, },
"matomo/device-detector": {
"version": "5.0.4"
},
"monolog/monolog": { "monolog/monolog": {
"version": "2.2.0" "version": "2.2.0"
}, },
"mustangostang/spyc": {
"version": "0.6.3"
},
"myclabs/php-enum": { "myclabs/php-enum": {
"version": "1.8.0" "version": "1.8.0"
}, },